Compare commits

...

110 Commits

Author SHA1 Message Date
屈轩
bd01cc9c95 fix(glance): add notify for image create (#23554) 2025-10-16 14:30:54 +08:00
wanyaoqi
6f5feb6a7f fix(webconsole): baremteasl ipmi sol instance_name hide password (#23549) 2025-10-16 00:01:59 +08:00
屈轩
23a8fefbd0 fix(region): valid essd pl0 disk resize (#23548) 2025-10-15 17:25:23 +08:00
屈轩
e04fe21a5c fix(region): vendor update (#23542) 2025-10-15 10:58:02 +08:00
屈轩
272e32c0b9 fix(region): support change storage type (#23532) 2025-10-14 19:06:24 +08:00
屈轩
bed77085c2 fix(region): healt status (#23527) 2025-10-13 18:51:19 +08:00
屈轩
c9f3c9578d fix(keystone): distribute permissions when the organization changes (#23504) 2025-10-13 18:50:01 +08:00
屈轩
8deaead935 fix(region): private zone create status (#23523) 2025-10-13 18:05:39 +08:00
wanyaoqi
87e65dab12 fix(host): ensure host wire marshal nil value (#23506) 2025-10-12 11:04:22 +08:00
屈轩
671e24b01e fix(region): server sku create with region id (#23511) 2025-10-11 16:55:15 +08:00
wanyaoqi
3d8ea72139 fix(region,glance,host-deployer): guest image support bios boot mode detect (#23380) 2025-10-11 10:21:21 +08:00
Zexi Li
70f29b481c fix(baremetal): ensure the execution of the BaremetalServerDestroyTask (#23496) 2025-10-09 17:07:18 +08:00
Jian Qiu
35cb610755 fix: ignore e2fsck errors if retcode < 4 (#23488)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-10-09 16:31:26 +08:00
wanyaoqi
62f44a77ff fix(host): disk resize error input params (#23492) 2025-10-09 13:27:13 +08:00
Jian Qiu
2ba9f0b887 fix: network manager supports ipv4 static routes for 3.11 (#23485)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-10-08 13:17:43 +08:00
Jian Qiu
1e676fb2e8 fix: default cloud region init error (#23471)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-10-03 06:33:12 +08:00
Jian Qiu
cfc6d56361 fix: support network manager connection profiles (#23466)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-10-03 00:19:17 +08:00
屈轩
f50929bc60 fix(region): vendor update (#23465) 2025-09-30 19:09:48 +08:00
屈轩
2ebbfb4dd9 fix(cloudmon): metric sync (#23464) 2025-09-30 16:53:10 +08:00
屈轩
feb6a1981f fix(region): vendor update (#23461) 2025-09-30 15:13:34 +08:00
屈轩
ded669c7a2 fix(region): host order by virt cpu (#23456) 2025-09-30 13:19:11 +08:00
Jian Qiu
2241f34b9b fix: update vendor 20250930 3.11.12 (#23454)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-09-30 13:17:08 +08:00
Jian Qiu
59ad7f73e8 fix: hostman master nic may be nil (#23449)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-09-30 11:17:49 +08:00
Jian Qiu
2b08c946ff fix: s3 common options (#23442)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-09-29 18:15:44 +08:00
Jian Qiu
4f0ca33bf9 fix: disable password history unique check by default (#23437)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-09-29 15:48:14 +08:00
屈轩
340d246ee5 fix(region): vendor update (#23418) 2025-09-28 18:04:20 +08:00
wanyaoqi
ae0920476b fix(host-deployer): update host-deployer-base to 1.4.11 (#23411) 2025-09-28 17:25:40 +08:00
屈轩
2ffa2cf4ca fix(region): vendor update (#23407) 2025-09-28 14:59:10 +08:00
wanyaoqi
cc4fdf189a Automated cherry pick of #23374: fix(region,host): guest add vnc screen dump support (#23379)
* fix(host): update nic confs inside vm on qga delete nics

Signed-off-by: wanyaoqi <wanyaoqi@yunion.cn>

* fix(region,host): guest add vnc screen dump support

---------

Signed-off-by: wanyaoqi <wanyaoqi@yunion.cn>
2025-09-27 12:03:35 +08:00
wanyaoqi
5ab6e57d73 fix(host-deployer): allow growpart on primary partition (#23386)
* fix(host): init cgroup ignore disable cgroup option

* fix(host-deployer): allow growpart on primary partition
2025-09-27 12:01:32 +08:00
屈轩
0ec0162857 fix(region): vendor update (#23400) 2025-09-26 18:05:35 +08:00
屈轩
f00099e29f fix(region): vendor update (#23385) 2025-09-26 13:53:52 +08:00
屈轩
0bbc92e46d fix(region): vendor update (#23369) 2025-09-24 17:22:57 +08:00
Jian Qiu
4c3186f4a1 Automated cherry pick of #23363: fix: network filter by ip error for dameng (#23366)
* fix: network filter by ip error for dameng

* fix: update vendor 20250923

---------

Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-09-23 23:23:00 +08:00
屈轩
6722c43868 fix(region): add expired release notify hour options (#23350) 2025-09-22 10:58:08 +08:00
Jian Qiu
e4391b9cce fix: linux sshd_config support (#23336)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-09-20 00:39:04 +08:00
Zexi Li
70887c8d58 fix(scheduler): watch serversku (#23327) 2025-09-19 23:49:56 +08:00
屈轩
66840c2c16 fix(region): rds backup sync (#23307) 2025-09-19 23:47:16 +08:00
wanyaoqi
34b417c60b fix(host,host-deployer): support lvm disk resize (#23333)
- add resize lvm disk support
- support qga online resize disk partitions and filesystems
2025-09-19 23:45:47 +08:00
Jian Qiu
b96abf5af6 fix: check os_arch when server rebuilding root (#23337)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-09-19 23:44:20 +08:00
屈轩
433747ff99 fix(notify): optimized workwx access token expired time (#23324) 2025-09-18 14:55:28 +08:00
Zexi Li
614b13cd13 fix(monitor): diffTagKeys are empty when only one series in results (#23310) 2025-09-18 07:49:04 +08:00
屈轩
d7f0a6f065 fix(region): remove debug sql (#23319) 2025-09-17 16:54:29 +08:00
屈轩
160b6e3faf fix(cloudmon): alert metric with tenant id (#23316) 2025-09-17 16:34:51 +08:00
wanyaoqi
7a82d04f70 feat(host): cgroupv2 support (#23304) 2025-09-16 23:20:18 +08:00
屈轩
104c927e74 fix(climc): sku create params (#23300) 2025-09-15 15:33:30 +08:00
屈轩
2d795063dd fix(region): support gcp shared vpc and image (#23297) 2025-09-12 23:03:39 +08:00
屈轩
e0ed7e80df fix(monitor): history alert report (#23279) 2025-09-12 15:27:12 +08:00
Zexi Li
c880ee5940 fix(monitor): fetch total alert resources from monitor_resource_alert (#23274) 2025-09-10 19:17:20 +08:00
屈轩
88f61e6be2 fix(region): update cloudprovider external id (#23273) 2025-09-10 18:59:58 +08:00
Jian Qiu
0777418c63 fix: image self check status (#23252)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-09-10 18:57:53 +08:00
屈轩
3ddd2603f8 fix(region): support hyperdisk for gcp (#23270) 2025-09-10 15:34:24 +08:00
Zexi Li
1a4a0fe647 fix(climc): monitor-alertrecords-total-alert command (#23265) 2025-09-10 14:17:41 +08:00
屈轩
0c090d08f2 fix(region): snapshot policy unbind disks (#23240) 2025-09-04 16:57:38 +08:00
屈轩
c37b15a3d0 fix(region): sync prepaid disk expired time (#23237) 2025-09-04 16:47:18 +08:00
屈轩
0eb0f9d99c fix(region): add disk change billing type log (#23233) 2025-09-03 20:16:44 +08:00
屈轩
620fd06d87 fix(region): add kafka and mongodb capability (#23230) 2025-09-03 19:44:40 +08:00
屈轩
944267af35 fix(region): support more scheme keypair (#23211) 2025-09-03 11:01:00 +08:00
Jian Qiu
f40095bd46 fix: fail to delete cas idp due to readonly domain (#23216)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-09-03 05:48:27 +08:00
Jian Qiu
4781f552e2 fix: network filter by ipv6 address (#23226)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-09-03 05:46:31 +08:00
Zexi Li
8eb11e7865 feat(host): add SdnFetchDataFromComputeService option (#23205) 2025-09-01 23:15:22 +08:00
屈轩
523653e755 fix(region): avoid change to the same config sku not effective (#23204) 2025-09-01 11:50:23 +08:00
Jian Qiu
84dea5ace9 fix: too many recursive locks when batch create (#23197)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-29 23:07:50 +08:00
屈轩
07912a9f8c fix(region): add cloud_env filter for cachedimages (#23192) 2025-08-27 18:34:46 +08:00
Jian Qiu
bd72a48ecb fix: guest ipv6 vip (#23181)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-27 18:07:55 +08:00
Jian Qiu
4377da3aff fix: force NetworkManager unmanged physical netinterface (#23069)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-26 15:38:55 +08:00
屈轩
140fda72e6 fix(keystone): show ldap url (#23175) 2025-08-26 14:28:47 +08:00
屈轩
521bc94749 fix(keystone): upgrade ldap version (#23167) 2025-08-26 13:28:47 +08:00
Jian Qiu
78850c6d03 fix: deploy gai.conf if both v4 and v6 present (#23164)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-25 18:20:09 +08:00
屈轩
32b85c1b28 fix(region): optimized cached image list (#23156) 2025-08-22 15:45:04 +08:00
wanyaoqi
ea65acf6ed fix(scheduler): add session usage timeout options (#23142) 2025-08-21 18:10:39 +08:00
屈轩
f09e9f081d fix(region): avoid update guest disable_delete attribute error when host id is empty (#23136) 2025-08-20 16:21:44 +08:00
Zexi Li
78eaa50af1 fix(baremetal): update the grub auto configuration to fix the aarch64 disk boot (#23127) 2025-08-20 15:11:14 +08:00
屈轩
d9e8c89711 fix(region): sync lb eip (#23126) 2025-08-20 14:14:07 +08:00
Zexi Li
3b34ac8dba feat(region): fix ISO size display (#23130)
SGuestcdrom.Size is Byte, not MB

Co-authored-by: happygame <happygame1024@gmail.com>
2025-08-20 12:08:43 +08:00
Zexi Li
b93d913948 fix(baremetal-agent): error occurred when removing logical volumes on the arm64 host (#23120) 2025-08-20 12:00:00 +08:00
屈轩
7d2bcd2828 fix(region): sync eip associate resource (#23113) 2025-08-19 14:54:55 +08:00
屈轩
76d798044e fix(region): add storage filter for snapshot (#23107) 2025-08-18 14:57:48 +08:00
wanyaoqi
382d51e18c fix(host): run ifdown script on guest delete (#23100) 2025-08-16 14:49:27 +08:00
Jian Qiu
a316053a4f fix: webconsole skip refererer check by default (#23093)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-16 14:46:16 +08:00
wanyaoqi
634058a832 fix(vpcagent): dhcp enable default gateway on default network (#23096) 2025-08-16 14:44:28 +08:00
屈轩
4c2ba4a9c9 fix(scheduledtask): force sync account (#23086) 2025-08-14 19:36:19 +08:00
屈轩
e244be79b1 fix(region): server snapshot policy (#23079) 2025-08-14 19:21:22 +08:00
屈轩
6615224f93 fix(region): dns record policy type (#23077) 2025-08-13 17:48:39 +08:00
wanyaoqi
555d77f9d0 fix(host): lvm guest reload disk before delete snapshot (#23048) 2025-08-11 10:32:50 +08:00
wanyaoqi
c15d5ba838 fix(baremetal): agent storagecache input params error (#23044) 2025-08-08 18:25:14 +08:00
Jian Qiu
5fce56f5e6 fix: filter guest by multiple ips with exact match (#23040)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-08 17:56:20 +08:00
屈轩
9a5b906d10 fix(region): disk update tag (#23026) 2025-08-06 15:52:17 +08:00
Jian Qiu
4d45708d11 fix: always update hostname for rhel-like os (#23019)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-08-06 01:07:38 +08:00
Jian Qiu
1f39911996 fix: inconsist checksum between image and its same format subimage (#22989)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-30 01:44:47 +08:00
wanyaoqi
d3154a0cde fix(host,glance): only target qcow2 set cluster size on image convert (#22976) 2025-07-30 00:42:30 +08:00
Jian Qiu
a5e4471e1f fix: glance converts all queued subimages, regardless of format (#22970)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-29 10:25:55 +08:00
wanyaoqi
c00c81f23b fix(host): set qemuimg convert cluster_size 64k on compat image (#22964) 2025-07-29 00:00:57 +08:00
Jian Qiu
061988edea fix: set default worker parameter (#22960)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-28 14:12:39 +08:00
wanyaoqi
7d453caff6 fix(region): iso boot do not check boot mode (#22948) 2025-07-26 02:26:40 +08:00
屈轩
c231b0bc66 fix(apigateway): 移除不必要查询,避免用户登录时间过长 (#22954) 2025-07-25 20:36:44 +08:00
wanyaoqi
d83fd7490a fix(host): host init no numa node (#22947) 2025-07-25 00:33:16 +08:00
屈轩
1d7b27e5e3 fix(region): add guest billing type for disk (#22937) 2025-07-23 18:53:56 +08:00
屈轩
1f083d2490 fix(region): host order (#22928) 2025-07-22 15:20:06 +08:00
屈轩
e7227612ea fix(region): vendor update (#22921) 2025-07-21 17:33:40 +08:00
Jian Qiu
e304c99316 fix: updte vendor 3.11.11 20250718 (#22915)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
2025-07-18 13:26:50 +08:00
Zexi Li
6c4c73c79e fix(scheduler): netinterface cache is not informed (#22898) 2025-07-15 19:58:11 +08:00
wanyaoqi
ba9457df30 fix(host): check storage id is correct on src migrate prepare (#22891)
correct disk storage id on dest migrate prepare
2025-07-15 16:12:00 +08:00
屈轩
5027e6bbde fix(region): add sort for host (#22878) 2025-07-11 19:09:04 +08:00
wanyaoqi
13060902a0 fix(region): do not set guest to resuce status on guest running (#22864) 2025-07-10 22:10:07 +08:00
屈轩
6c726c7211 fix(region): 修复本地到期释放功能和资源同步冲突 (#22862) 2025-07-10 19:38:09 +08:00
wanyaoqi
1b6f13738a fix(host): add check mem dev is null on guest setup (#22846) 2025-07-09 14:15:40 +08:00
屈轩
4455aa2f6d fix(region): 避免删除虚拟机时,未能正常删除后挂载的磁盘 (#22844) 2025-07-07 14:46:23 +08:00
屈轩
345de4a5c3 fix(region): create disk with tags (#22835) 2025-07-04 17:08:12 +08:00
屈轩
944953957e fix(region): vendor update (#22831) 2025-07-03 15:17:01 +08:00
555 changed files with 40533 additions and 4642 deletions

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

@@ -86,4 +86,7 @@ type CachedimageListInput struct {
// valid cachedimage
Valid bool `json:"valid"`
// enum: [public, private]
CloudEnv string `json:"cloud_env"`
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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() {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -38,4 +38,8 @@ const (
CLOUDPODS = "cloudpods"
PROXMOX = "proxmox"
VOLC_ENGINE = "volcengine"
BAIDU = "baidu"
SANGFOR = "sangfor"
CNWARE = "cnware"
KSYUN = "ksyun"
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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{})
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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, ".")

View 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
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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