mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-19 10:46:58 +08:00
Merge branch 'release/2.4.0' of ssh://git.yunion.io/~qiujian/onecloud into hotfix/qj-policy-cache
This commit is contained in:
Generated
+9
-8
@@ -1312,11 +1312,11 @@
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:a2346cf0c965791c281a428a3e9bf522913941028e4c814a774af7f3cc2360b0"
|
||||
digest = "1:3c2ee66e652654aae64107ab7e0087cfb05a959b2e22ff75880d0cd7b47e695d"
|
||||
name = "yunion.io/x/jsonutils"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "814e036849815935e5957ebd03bd0f4fc992fe83"
|
||||
revision = "0233c7b766f65b0ebbe6f72717f141405afbb496"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -1331,7 +1331,7 @@
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:5293df1051bc3efc179027b9250533e5ece1da66ab03bbfb00384c18b9916282"
|
||||
digest = "1:6d91d27a4867494b3fdaa177e519f13ee45dbb0c246c9b7ed05ea7a586ebb9a4"
|
||||
name = "yunion.io/x/pkg"
|
||||
packages = [
|
||||
"gotypes",
|
||||
@@ -1364,23 +1364,23 @@
|
||||
"utils",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "9ea65d37be78406707a313fdecb17aa392199575"
|
||||
revision = "a8af02b7adb621ab73bb094330e2c0c3adbfbf90"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:5a3958d2f3c6c6510cc6b0e754cc45f6e98d8f8780ea04c1232a8f22fd6d91fc"
|
||||
digest = "1:2fdf064ae928c1b311e67ec51e856ce655abc39e8eacf5e6b3f7bd0417fac0a6"
|
||||
name = "yunion.io/x/sqlchemy"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "30271a36b97155505642d6d3709a37600aade302"
|
||||
revision = "e22221d5efcc667e68b0fdeed19958e788c3ad63"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:bbaf572e68e5dad4045e1e424af29838882c620df391fa1631dd8dc851c87a95"
|
||||
digest = "1:97c47d46b272f535bc6760672a3dd4512bf66fb4463cb70547178e21cf9078f7"
|
||||
name = "yunion.io/x/structarg"
|
||||
packages = ["."]
|
||||
pruneopts = "UT"
|
||||
revision = "c95bf78846decd8dea379e925410f2895fb20076"
|
||||
revision = "1a162c0cfa82905f20a795e9ac530bf27f9a0549"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
@@ -1434,6 +1434,7 @@
|
||||
"github.com/coredns/coredns/request",
|
||||
"github.com/fatih/color",
|
||||
"github.com/go-sql-driver/mysql",
|
||||
"github.com/golang-plus/errors",
|
||||
"github.com/golang-plus/uuid",
|
||||
"github.com/googollee/go-socket.io",
|
||||
"github.com/gorilla/mux",
|
||||
|
||||
@@ -43,9 +43,11 @@ install: prepare_dir
|
||||
done
|
||||
|
||||
|
||||
build:
|
||||
build: gendoc
|
||||
$(MAKE) $(wildcard cmd/*)
|
||||
|
||||
gendoc:
|
||||
@sh build/gendoc.sh
|
||||
|
||||
test:
|
||||
@for PKG in $$( $(PKGS) | grep "$(filter-out $@,$(MAKECMDGOALS))" ); do \
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
for top in pkg
|
||||
do
|
||||
for d in $(find $top -type d)
|
||||
do
|
||||
if [ ! -f $d/doc.go ]; then
|
||||
if ls $d/*.go > /dev/null 2>&1; then
|
||||
echo $d/doc.go
|
||||
echo "package $(basename $d) // import \"yunion.io/x/onecloud/$d\"" > $d/doc.go
|
||||
fi
|
||||
fi
|
||||
done
|
||||
done
|
||||
+12
-31
@@ -11,40 +11,21 @@ import (
|
||||
func init() {
|
||||
type DiskListOptions struct {
|
||||
options.BaseListOptions
|
||||
Unused bool `help:"Show unused disks"`
|
||||
Share bool `help:"Show Share storage disks"`
|
||||
Local bool `help:"Show Local storage disks"`
|
||||
Guest string `help:"Guest ID or name"`
|
||||
Storage string `help:"Storage ID or name"`
|
||||
|
||||
Unused *bool `help:"Show unused disks"`
|
||||
Share *bool `help:"Show Share storage disks"`
|
||||
Local *bool `help:"Show Local storage disks"`
|
||||
Guest string `help:"Guest ID or name"`
|
||||
Storage string `help:"Storage ID or name"`
|
||||
|
||||
Provider string `help:"Provider for disk" choices:"Aliyun|VMware|Azure"`
|
||||
|
||||
BillingType string `help:"billing type" choices:"postpaid|prepaid"`
|
||||
}
|
||||
R(&DiskListOptions{}, "disk-list", "List virtual disks", func(s *mcclient.ClientSession, suboptions *DiskListOptions) error {
|
||||
var params *jsonutils.JSONDict
|
||||
{
|
||||
var err error
|
||||
params, err = suboptions.BaseListOptions.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
}
|
||||
if suboptions.Unused {
|
||||
params.Add(jsonutils.JSONTrue, "unused")
|
||||
}
|
||||
if suboptions.Share {
|
||||
params.Add(jsonutils.JSONTrue, "share")
|
||||
}
|
||||
if suboptions.Local {
|
||||
params.Add(jsonutils.JSONTrue, "local")
|
||||
}
|
||||
if len(suboptions.Guest) > 0 {
|
||||
params.Add(jsonutils.NewString(suboptions.Guest), "guest")
|
||||
}
|
||||
if len(suboptions.Storage) > 0 {
|
||||
params.Add(jsonutils.NewString(suboptions.Storage), "storage")
|
||||
}
|
||||
if len(suboptions.Provider) > 0 {
|
||||
params.Add(jsonutils.NewString(suboptions.Provider), "provider")
|
||||
params, err := options.ListStructToParams(suboptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.Disks.List(s, params)
|
||||
if err != nil {
|
||||
|
||||
@@ -22,9 +22,11 @@ func init() {
|
||||
Occupied bool `help:"show occupid host"`
|
||||
Enabled bool `help:"Show enabled host only"`
|
||||
Disabled bool `help:"Show disabled host only"`
|
||||
HostType string `help:"Host type filter" choices:"baremetal|hypervisor|esxi|kubelet|hyperv"`
|
||||
HostType string `help:"Host type filter" choices:"baremetal|hypervisor|esxi|kubelet|hyperv|aliyun|azure|qcloud|aws|huawei"`
|
||||
AnyMac string `help:"Mac matches one of the host's interface"`
|
||||
|
||||
ResourceType string `help:"Resource type" choices:"shared|prepaid|dedicated"`
|
||||
|
||||
Manager string `help:"Show regions belongs to the cloud provider"`
|
||||
Usable bool `help:"List all zones that is usable"`
|
||||
|
||||
@@ -64,6 +66,9 @@ func init() {
|
||||
if len(args.HostType) > 0 {
|
||||
params.Add(jsonutils.NewString(args.HostType), "host_type")
|
||||
}
|
||||
if len(args.ResourceType) > 0 {
|
||||
params.Add(jsonutils.NewString(args.ResourceType), "resource_type")
|
||||
}
|
||||
|
||||
if len(args.Manager) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Manager), "manager")
|
||||
@@ -403,12 +408,24 @@ func init() {
|
||||
})
|
||||
|
||||
type HostEnableNetIfOptions struct {
|
||||
ID string `help:"ID or Name of host"`
|
||||
MAC string `help:"MAC of NIC to enable"`
|
||||
ID string `help:"ID or Name of host"`
|
||||
MAC string `help:"MAC of NIC to enable"`
|
||||
Ip string `help:"IP address"`
|
||||
Network string `help:"network to connect"`
|
||||
Reserved bool `help:"fetch IP from reserved pool"`
|
||||
}
|
||||
R(&HostEnableNetIfOptions{}, "host-enable-netif", "Enable a network interface for a host", func(s *mcclient.ClientSession, args *HostEnableNetIfOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.MAC), "mac")
|
||||
if len(args.Ip) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Ip), "ip_addr")
|
||||
if args.Reserved {
|
||||
params.Add(jsonutils.JSONTrue, "reserve")
|
||||
}
|
||||
}
|
||||
if len(args.Network) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Network), "network")
|
||||
}
|
||||
result, err := modules.Hosts.PerformAction(s, args.ID, "enable-netif", params)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -512,4 +529,16 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type HostUndoPrepaidRecycleOptions struct {
|
||||
ID string `help:"ID or name of host to undo recycle"`
|
||||
}
|
||||
R(&HostUndoPrepaidRecycleOptions{}, "host-undo-recycle", "Pull a prepaid server from recycle pool, so that it will not be shared any more", func(s *mcclient.ClientSession, args *HostUndoPrepaidRecycleOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
result, err := modules.Hosts.PerformAction(s, args.ID, "undo-prepaid-recycle", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -57,6 +58,17 @@ func init() {
|
||||
return err
|
||||
}
|
||||
|
||||
if opts.GenerateName {
|
||||
params.Add(jsonutils.NewString(opts.NAME), "generate_name")
|
||||
} else {
|
||||
params.Add(jsonutils.NewString(opts.NAME), "name")
|
||||
}
|
||||
if regutils.MatchSize(opts.MEMSPEC) {
|
||||
params.Add(jsonutils.NewString(opts.MEMSPEC), "vmem_size")
|
||||
} else {
|
||||
params.Add(jsonutils.NewString(opts.MEMSPEC), "instance_type")
|
||||
}
|
||||
|
||||
if opts.NoAccountInit != nil && *opts.NoAccountInit {
|
||||
params.Add(jsonutils.JSONFalse, "reset_password")
|
||||
}
|
||||
@@ -592,4 +604,43 @@ func init() {
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type ServerRenewOptions struct {
|
||||
ID string `help:"ID or name of server to renew"`
|
||||
DURATION string `help:"Duration of renew, ADMIN only command"`
|
||||
}
|
||||
R(&ServerRenewOptions{}, "server-renew", "Renew a server", func(s *mcclient.ClientSession, args *ServerRenewOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.DURATION), "duration")
|
||||
result, err := modules.Servers.PerformAction(s, args.ID, "renew", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
type ServerPrepaidRecycleOptions struct {
|
||||
ID string `help:"ID or name of server to recycle"`
|
||||
}
|
||||
R(&ServerPrepaidRecycleOptions{}, "server-enable-recycle", "Put a prepaid server into recycle pool, so that it can be shared", func(s *mcclient.ClientSession, args *ServerPrepaidRecycleOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
result, err := modules.Servers.PerformAction(s, args.ID, "prepaid-recycle", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&ServerPrepaidRecycleOptions{}, "server-disable-recycle", "Pull a prepaid server from recycle pool, so that it will not be shared anymore", func(s *mcclient.ClientSession, args *ServerPrepaidRecycleOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
result, err := modules.Servers.PerformAction(s, args.ID, "undo-prepaid-recycle", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
+17
-3
@@ -1,6 +1,8 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
@@ -9,12 +11,24 @@ import (
|
||||
func init() {
|
||||
type ServerSkusListOptions struct {
|
||||
options.BaseListOptions
|
||||
Provider string `help:"provider" choices:"all|kvm|esxi|xen|hyperv|aliyun|azure|aws|qcloud|huawei"`
|
||||
Region string `help:"region Id or name"`
|
||||
Zone string `help:"zone Id or name"`
|
||||
Cpu int `help:"Cpu core count"`
|
||||
Mem int `help:"Memory size in MB"`
|
||||
Name string `help:"Name of Sku"`
|
||||
}
|
||||
R(&ServerSkusListOptions{}, "server-sku-list", "List all avaiable Server SKU", func(s *mcclient.ClientSession, args *ServerSkusListOptions) error {
|
||||
params, err := options.ListStructToParams(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if args.Cpu > 0 {
|
||||
params.Add(jsonutils.NewInt(int64(args.Cpu)), "cpu_core_count")
|
||||
}
|
||||
if args.Mem > 0 {
|
||||
params.Add(jsonutils.NewInt(int64(args.Mem)), "memory_size_mb")
|
||||
}
|
||||
results, err := modules.ServerSkus.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -39,6 +53,7 @@ func init() {
|
||||
Name string `help:"Name ID of SKU" required:"true" positional:"true"`
|
||||
CpuCoreCount int `help:"Cpu Count" required:"true" positional:"true"`
|
||||
MemorySizeMB int `help:"Memory MB" required:"true" positional:"true"`
|
||||
Provider string `help:"Provider name" choices:"kvm|esxi"`
|
||||
|
||||
OsName *string `help:"OS name/type" choices:"Linux|Windows|Any" default:"Any"`
|
||||
SkuFamily *string `help:"sku family"`
|
||||
@@ -61,9 +76,8 @@ func init() {
|
||||
GPUCount *int `help:"GPU count"`
|
||||
GPUAttachable *bool `help:"Allow attach GPU"`
|
||||
|
||||
Zone *string `help:"Zone ID or name"`
|
||||
Region *string `help:"Region ID or name"`
|
||||
Provider *string `help:"Provider name" choices:"kvm|esxi"`
|
||||
Zone *string `help:"Zone ID or name"`
|
||||
Region *string `help:"Region ID or name"`
|
||||
}
|
||||
R(&ServerSkusCreateOptions{}, "server-sku-create", "Create a server sku record", func(s *mcclient.ClientSession, args *ServerSkusCreateOptions) error {
|
||||
params, err := options.StructToParams(args)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
type GeneralUsageOptions struct {
|
||||
HostType []string `help:"Host types" choices:"hypervisor|baremetal|esxi|xen|kubelet|hyperv|aliyun|azure|aws|huawei|qcloud"`
|
||||
Provider []string `help:"Provider" choices:"VMware|Aliyun|Azure|Aws|Qcloud|Huawei"`
|
||||
Project string
|
||||
}
|
||||
|
||||
@@ -16,6 +17,9 @@ func fetchHostTypeOptions(args *GeneralUsageOptions) *jsonutils.JSONDict {
|
||||
if len(args.HostType) > 0 {
|
||||
params.Add(jsonutils.NewStringArray(args.HostType), "host_type")
|
||||
}
|
||||
if len(args.Provider) > 0 {
|
||||
params.Add(jsonutils.NewStringArray(args.Provider), "provider")
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
@@ -61,9 +65,21 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&ResourceUsageOptions{}, "vcenter-usage", "Show general usage of vcenter", func(s *mcclient.ClientSession, args *ResourceUsageOptions) error {
|
||||
R(&ResourceUsageOptions{}, "cloud-provider-usage", "Show general usage of vcenter", func(s *mcclient.ClientSession, args *ResourceUsageOptions) error {
|
||||
params := fetchHostTypeOptions(&args.GeneralUsageOptions)
|
||||
params.Add(jsonutils.NewString("vcenters"), "range_type")
|
||||
params.Add(jsonutils.NewString("cloudproviders"), "range_type")
|
||||
params.Add(jsonutils.NewString(args.ID), "range_id")
|
||||
result, err := modules.Usages.GetGeneralUsage(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&ResourceUsageOptions{}, "cloud-account-usage", "Show general usage of vcenter", func(s *mcclient.ClientSession, args *ResourceUsageOptions) error {
|
||||
params := fetchHostTypeOptions(&args.GeneralUsageOptions)
|
||||
params.Add(jsonutils.NewString("cloudaccounts"), "range_type")
|
||||
params.Add(jsonutils.NewString(args.ID), "range_id")
|
||||
result, err := modules.Usages.GetGeneralUsage(s, params)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package test // import "yunion.io/x/onecloud/pkg/appsrv/test"
|
||||
@@ -0,0 +1 @@
|
||||
package consts // import "yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
@@ -12,6 +12,8 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
)
|
||||
|
||||
type TCronJobFunction func(ctx context.Context, userCred mcclient.TokenCredential, isStart bool)
|
||||
|
||||
var manager *SCronJobManager
|
||||
|
||||
func init() {
|
||||
@@ -43,7 +45,7 @@ func (t *Timer2) Next(now time.Time) time.Time {
|
||||
|
||||
type SCronJob struct {
|
||||
Name string
|
||||
job func(ctx context.Context, userCred mcclient.TokenCredential)
|
||||
job TCronJobFunction
|
||||
Timer ICronTimer
|
||||
Next time.Time
|
||||
StartRun bool
|
||||
@@ -92,7 +94,7 @@ func GetCronJobManager() *SCronJobManager {
|
||||
return manager
|
||||
}
|
||||
|
||||
func (self *SCronJobManager) AddJob1(name string, interval time.Duration, jobFunc func(ctx context.Context, userCred mcclient.TokenCredential)) {
|
||||
func (self *SCronJobManager) AddJob1(name string, interval time.Duration, jobFunc TCronJobFunction) {
|
||||
t := Timer1{
|
||||
dur: interval,
|
||||
}
|
||||
@@ -108,7 +110,7 @@ func (self *SCronJobManager) AddJob1(name string, interval time.Duration, jobFun
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SCronJobManager) AddJob2(name string, day, hour, min, sec int, jobFunc func(ctx context.Context, userCred mcclient.TokenCredential), startRun bool) {
|
||||
func (self *SCronJobManager) AddJob2(name string, day, hour, min, sec int, jobFunc TCronJobFunction, startRun bool) {
|
||||
t := Timer2{
|
||||
day: day,
|
||||
hour: hour,
|
||||
@@ -160,7 +162,7 @@ func (self *SCronJobManager) run() {
|
||||
for i := 0; i < len(self.jobs); i += 1 {
|
||||
if self.jobs[i].StartRun {
|
||||
self.jobs[i].StartRun = false
|
||||
self.jobs[i].runJob()
|
||||
self.jobs[i].runJob(true)
|
||||
}
|
||||
}
|
||||
select {
|
||||
@@ -169,7 +171,7 @@ func (self *SCronJobManager) run() {
|
||||
if job.Next.After(now) || job.Next.IsZero() {
|
||||
break
|
||||
}
|
||||
go job.runJob()
|
||||
go job.runJob(false)
|
||||
job.Next = job.Timer.Next(now)
|
||||
heap.Fix(&self.jobs, i)
|
||||
}
|
||||
@@ -184,7 +186,7 @@ func (self *SCronJobManager) run() {
|
||||
}
|
||||
}
|
||||
|
||||
func (job *SCronJob) runJob() {
|
||||
func (job *SCronJob) runJob(isStart bool) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Errorf("CronJob task %s run error: %s", job.Name, r)
|
||||
@@ -196,5 +198,5 @@ func (job *SCronJob) runJob() {
|
||||
ctx := context.Background()
|
||||
ctx = context.WithValue(ctx, appctx.APP_CONTEXT_KEY_APPNAME, "Region-Corn-Service")
|
||||
userCred := auth.AdminCredential()
|
||||
job.job(ctx, userCred)
|
||||
job.job(ctx, userCred, isStart)
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package example // import "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman/example"
|
||||
@@ -150,6 +150,13 @@ const (
|
||||
ACT_GUEST_DETACH_ISOLATED_DEVICE_FAIL = "guest_detach_isolated_deivce_fail"
|
||||
|
||||
ACT_CHANGE_BANDWIDTH = "eip_change_bandwidth"
|
||||
|
||||
ACT_RENEW = "renew"
|
||||
|
||||
ACT_SCHEDULE = "schedule"
|
||||
|
||||
ACT_RECYCLE_PREPAID = "recycle_prepaid"
|
||||
ACT_UNDO_RECYCLE_PREPAID = "undo_recycle_prepaid"
|
||||
)
|
||||
|
||||
type SOpsLogManager struct {
|
||||
|
||||
@@ -13,7 +13,7 @@ type ITask interface {
|
||||
GetParams() *jsonutils.JSONDict
|
||||
GetUserCred() mcclient.TokenCredential
|
||||
GetTaskId() string
|
||||
SetStage(stageName string, data *jsonutils.JSONDict)
|
||||
SetStage(stageName string, data *jsonutils.JSONDict) error
|
||||
|
||||
GetTaskRequestHeader() http.Header
|
||||
|
||||
|
||||
@@ -398,8 +398,8 @@ func execITask(taskValue reflect.Value, task *STask, odata jsonutils.JSONObject,
|
||||
}
|
||||
task.taskObjects = objs
|
||||
|
||||
// lockman.LockClass(ctx, objResManager, task.UserCred.GetProjectId())
|
||||
// defer lockman.ReleaseClass(ctx, objResManager, task.UserCred.GetProjectId())
|
||||
lockman.LockClass(ctx, objResManager, task.UserCred.GetProjectId())
|
||||
defer lockman.ReleaseClass(ctx, objResManager, task.UserCred.GetProjectId())
|
||||
|
||||
params[1] = reflect.ValueOf(objs)
|
||||
} else {
|
||||
@@ -413,8 +413,8 @@ func execITask(taskValue reflect.Value, task *STask, odata jsonutils.JSONObject,
|
||||
}
|
||||
task.taskObject = obj
|
||||
|
||||
// lockman.LockObject(ctx, obj)
|
||||
// defer lockman.ReleaseObject(ctx, obj)
|
||||
lockman.LockObject(ctx, obj)
|
||||
defer lockman.ReleaseObject(ctx, obj)
|
||||
|
||||
params[1] = reflect.ValueOf(obj)
|
||||
}
|
||||
@@ -470,30 +470,37 @@ func (self *STask) SaveRequestContext(data *appctx.AppContextData) {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *STask) SetStage(stageName string, data *jsonutils.JSONDict) {
|
||||
func (self *STask) SaveParams(data *jsonutils.JSONDict) error {
|
||||
return self.SetStage("", data)
|
||||
}
|
||||
|
||||
func (self *STask) SetStage(stageName string, data *jsonutils.JSONDict) error {
|
||||
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Update(self.Params)
|
||||
if data != nil {
|
||||
params.Update(data)
|
||||
}
|
||||
stages, _ := params.Get("__stages")
|
||||
if stages == nil {
|
||||
stages = jsonutils.NewArray()
|
||||
params.Add(stages, "__stages")
|
||||
if len(stageName) > 0 {
|
||||
stages, _ := params.Get("__stages")
|
||||
if stages == nil {
|
||||
stages = jsonutils.NewArray()
|
||||
params.Add(stages, "__stages")
|
||||
}
|
||||
stageList := stages.(*jsonutils.JSONArray)
|
||||
stageData := jsonutils.NewDict()
|
||||
stageData.Add(jsonutils.NewString(self.Stage), "name")
|
||||
stageData.Add(jsonutils.NewTimeString(time.Now()), "complete_at")
|
||||
stageList.Add(stageData)
|
||||
self.Stage = stageName
|
||||
}
|
||||
stageList := stages.(*jsonutils.JSONArray)
|
||||
stageData := jsonutils.NewDict()
|
||||
stageData.Add(jsonutils.NewString(self.Stage), "name")
|
||||
stageData.Add(jsonutils.NewTimeString(time.Now()), "complete_at")
|
||||
stageList.Add(stageData)
|
||||
self.Stage = stageName
|
||||
self.Params = params
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("set_stage fail %s", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *STask) GetObjectIdStr() string {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package policy // import "yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
||||
@@ -99,6 +99,18 @@ var (
|
||||
Action: PolicyActionGet,
|
||||
Result: rbacutils.OwnerAllow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "serverskus",
|
||||
Action: PolicyActionList,
|
||||
Result: rbacutils.UserAllow,
|
||||
},
|
||||
{
|
||||
Service: "compute",
|
||||
Resource: "serverskus",
|
||||
Action: PolicyActionGet,
|
||||
Result: rbacutils.UserAllow,
|
||||
},
|
||||
{
|
||||
Service: "yunionagent",
|
||||
Resource: "notices",
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package policy
|
||||
|
||||
import (
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
@@ -32,7 +30,7 @@ func (self *SPolicyTokenCredential) IsAdminAllow(service string, resource string
|
||||
|
||||
func init() {
|
||||
gotypes.RegisterSerializableTransformer(mcclient.TokenCredentialType, func(input gotypes.ISerializable) gotypes.ISerializable {
|
||||
log.Debugf("do TokenCredential transform for %#v", input)
|
||||
// log.Debugf("do TokenCredential transform for %#v", input)
|
||||
switch val := input.(type) {
|
||||
case *mcclient.SSimpleToken:
|
||||
return &SPolicyTokenCredential{val}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
type ICloudResource interface {
|
||||
@@ -151,10 +152,10 @@ type ICloudHost interface {
|
||||
GetManagerId() string
|
||||
|
||||
CreateVM(name string, imgId string, sysDiskSize int, cpu int, memMB int, vswitchId string, ipAddr string, desc string,
|
||||
passwd string, storageType string, diskSizes []int, publicKey string, extSecGrpId string, userData string) (ICloudVM, error)
|
||||
passwd string, storageType string, diskSizes []int, publicKey string, extSecGrpId string, userData string, billingCycle *billing.SBillingCycle) (ICloudVM, error)
|
||||
// 使用instanceType创建实例。
|
||||
CreateVM2(name string, imgId string, sysDiskSize int, instanceType string, vswitchId string, ipAddr string, desc string,
|
||||
passwd string, storageType string, diskSizes []int, publicKey string, extSecGrpId string, userData string) (ICloudVM, error)
|
||||
passwd string, storageType string, diskSizes []int, publicKey string, extSecGrpId string, userData string, billingCycle *billing.SBillingCycle) (ICloudVM, error)
|
||||
|
||||
GetIHostNics() ([]ICloudHostNetInterface, error)
|
||||
}
|
||||
@@ -212,6 +213,8 @@ type ICloudVM interface {
|
||||
DetachDisk(ctx context.Context, diskId string) error
|
||||
|
||||
CreateDisk(ctx context.Context, sizeMb int, uuid string, driver string) error
|
||||
|
||||
Renew(bc billing.SBillingCycle) error
|
||||
}
|
||||
|
||||
type ICloudNic interface {
|
||||
@@ -297,6 +300,8 @@ type ICloudDisk interface {
|
||||
|
||||
Resize(ctx context.Context, newSizeMB int64) error
|
||||
Reset(ctx context.Context, snapshotId string) error
|
||||
|
||||
Rebuild(ctx context.Context) error
|
||||
}
|
||||
|
||||
type ICloudSnapshot interface {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package consts
|
||||
@@ -0,0 +1 @@
|
||||
package consts // import "yunion.io/x/onecloud/pkg/compute/consts"
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
"yunion.io/x/onecloud/pkg/util/seclib2"
|
||||
)
|
||||
|
||||
@@ -156,12 +157,18 @@ func (self *SAliyunGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gu
|
||||
|
||||
var createErr error
|
||||
var iVM cloudprovider.ICloudVM
|
||||
|
||||
var bc *billing.SBillingCycle
|
||||
if desc.BillingCycle.IsValid() {
|
||||
bc = &desc.BillingCycle
|
||||
}
|
||||
|
||||
if len(desc.InstanceType) > 0 {
|
||||
iVM, createErr = ihost.CreateVM2(desc.Name, desc.ExternalImageId, desc.SysDiskSize, desc.InstanceType, desc.ExternalNetworkId,
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData)
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData, bc)
|
||||
} else {
|
||||
iVM, createErr = ihost.CreateVM(desc.Name, desc.ExternalImageId, desc.SysDiskSize, desc.Cpu, desc.Memory, desc.ExternalNetworkId,
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData)
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData, bc)
|
||||
}
|
||||
|
||||
if createErr != nil {
|
||||
@@ -275,7 +282,7 @@ func (self *SAliyunGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gu
|
||||
if len(idisks) < len(desc.DataDisks)+1 {
|
||||
log.Debugf("inconsistent disk number???? %d != %d", len(idisks), len(desc.DataDisks)+1)
|
||||
}
|
||||
if idisks[0].GetGlobalId() != diskId {
|
||||
if len(idisks) > 0 && idisks[0].GetGlobalId() != diskId {
|
||||
log.Errorf("system disk id inconsistent %s != %s", idisks[0].GetGlobalId(), diskId)
|
||||
}
|
||||
time.Sleep(time.Second * 5)
|
||||
@@ -301,3 +308,15 @@ func (self *SAliyunGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gu
|
||||
func (self *SAliyunGuestDriver) AllowReconfigGuest() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SAliyunGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle) bool {
|
||||
weeks := bc.GetWeeks()
|
||||
if weeks >= 1 && weeks <= 4 {
|
||||
return true
|
||||
}
|
||||
months := bc.GetMonths()
|
||||
if (months >= 1 && months <= 10) || (months == 12) || (months == 24) || (months == 36) || (months == 48) || (months == 60) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
type SAwsGuestDriver struct {
|
||||
@@ -132,10 +133,10 @@ func (self *SAwsGuestDriver) RequestDeployGuestOnHost(ctx context.Context, guest
|
||||
var iVM cloudprovider.ICloudVM
|
||||
if len(desc.InstanceType) > 0 {
|
||||
iVM, createErr = ihost.CreateVM2(desc.Name, desc.ExternalImageId, desc.SysDiskSize, desc.InstanceType, desc.ExternalNetworkId,
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData)
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData, nil)
|
||||
} else {
|
||||
iVM, createErr = ihost.CreateVM(desc.Name, desc.ExternalImageId, desc.SysDiskSize, desc.Cpu, desc.Memory, desc.ExternalNetworkId,
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData)
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData, nil)
|
||||
}
|
||||
|
||||
if createErr != nil {
|
||||
@@ -242,3 +243,7 @@ func (self *SAwsGuestDriver) RequestDeployGuestOnHost(ctx context.Context, guest
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
type SAzureGuestDriver struct {
|
||||
@@ -180,10 +181,10 @@ func (self *SAzureGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gue
|
||||
var iVM cloudprovider.ICloudVM
|
||||
if len(desc.InstanceType) > 0 {
|
||||
iVM, createErr = ihost.CreateVM2(desc.Name, desc.ExternalImageId, desc.SysDiskSize, desc.InstanceType, desc.ExternalNetworkId,
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData)
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData, nil)
|
||||
} else {
|
||||
iVM, createErr = ihost.CreateVM(desc.Name, desc.ExternalImageId, desc.SysDiskSize, desc.Cpu, desc.Memory, desc.ExternalNetworkId,
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData)
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData, nil)
|
||||
}
|
||||
|
||||
if createErr != nil {
|
||||
@@ -319,3 +320,7 @@ func (self *SAzureGuestDriver) RequestSyncConfigOnHost(ctx context.Context, gues
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SAzureGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -247,12 +247,14 @@ func (self *SBaremetalGuestDriver) StartGuestSyncstatusTask(guest *models.SGuest
|
||||
|
||||
func (self *SBaremetalGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
var confs = make([]baremetal.BaremetalDiskConfig, 0)
|
||||
for data.Contains(fmt.Sprintf("baremetal_disk_config.%d", len(confs))) {
|
||||
desc, _ := data.GetString(fmt.Sprintf("baremetal_disk_config.%d", len(confs)))
|
||||
data.Remove(fmt.Sprintf("baremetal_disk_config.%d", len(confs)))
|
||||
jsonArray := jsonutils.GetArrayOfPrefix(data, "baremetal_disk_config")
|
||||
for i := 0; i < len(jsonArray); i += 1 {
|
||||
// for data.Contains(fmt.Sprintf("baremetal_disk_config.%d", len(confs))) {
|
||||
desc, _ := jsonArray[i].GetString() // data.GetString(fmt.Sprintf("baremetal_disk_config.%d", len(confs)))
|
||||
data.Remove(fmt.Sprintf("baremetal_disk_config.%d", i))
|
||||
bmConf, err := baremetal.ParseDiskConfig(desc)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("baremetal_disk_config.%d", len(confs))
|
||||
return nil, httperrors.NewInputParameterError("baremetal_disk_config.%d", i)
|
||||
}
|
||||
confs = append(confs, bmConf)
|
||||
}
|
||||
|
||||
@@ -8,10 +8,12 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"time"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
type SBaseGuestDriver struct {
|
||||
@@ -55,6 +57,13 @@ func (self *SBaseGuestDriver) StartGuestCreateTask(guest *models.SGuest, ctx con
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) OnGuestCreateTaskComplete(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
duration, _ := task.GetParams().GetString("duration")
|
||||
if len(duration) > 0 {
|
||||
bc, err := billing.ParseBillingCycle(duration)
|
||||
if err == nil && guest.ExpiredAt.IsZero() {
|
||||
guest.SaveRenewInfo(task.GetUserCred(), &bc, nil)
|
||||
}
|
||||
}
|
||||
if jsonutils.QueryBoolean(task.GetParams(), "auto_start", false) {
|
||||
task.SetStage("on_auto_start_guest", nil)
|
||||
return guest.StartGueststartTask(ctx, task.GetUserCred(), nil, task.GetTaskId())
|
||||
@@ -195,3 +204,11 @@ func (self *SBaseGuestDriver) GetMaxSecurityGroupCount() int {
|
||||
func (self *SBaseGuestDriver) getTaskRequestHeader(task taskman.ITask) http.Header {
|
||||
return task.GetTaskRequestHeader()
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SBaseGuestDriver) RequestRenewInstance(guest *models.SGuest, bc billing.SBillingCycle) (time.Time, error) {
|
||||
return time.Time{}, nil
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"time"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
type SESXiGuestDriver struct {
|
||||
@@ -150,7 +152,7 @@ func (self *SESXiGuestDriver) OnGuestDeployTaskDataReceived(ctx context.Context,
|
||||
if host.Id != guest.HostId {
|
||||
models.HostManager.ClearSchedDescCache(host.Id)
|
||||
models.HostManager.ClearSchedDescCache(guest.HostId)
|
||||
guest.SetHostId(host.Id)
|
||||
guest.OnScheduleToHost(ctx, task.GetUserCred(), host.Id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,3 +171,7 @@ func (self *SESXiGuestDriver) DoGuestCreateDisksTask(ctx context.Context, guest
|
||||
subtask.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SESXiGuestDriver) RequestRenewInstance(guest *models.SGuest, bc billing.SBillingCycle) (time.Time, error) {
|
||||
return time.Time{}, nil
|
||||
}
|
||||
|
||||
@@ -10,11 +10,13 @@ import (
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
|
||||
"time"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
type SManagedVirtualizedGuestDriver struct {
|
||||
@@ -39,6 +41,8 @@ type SManagedVMCreateConfig struct {
|
||||
SecGroupId string
|
||||
SecGroupName string
|
||||
SecRules []secrules.SecurityRule
|
||||
|
||||
BillingCycle billing.SBillingCycle
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) GetJsonDescAtHost(ctx context.Context, guest *models.SGuest, host *models.SHost) jsonutils.JSONObject {
|
||||
@@ -48,14 +52,7 @@ func (self *SManagedVirtualizedGuestDriver) GetJsonDescAtHost(ctx context.Contex
|
||||
config.Memory = guest.VmemSize
|
||||
config.Description = guest.Description
|
||||
|
||||
if len(guest.SkuId) > 0 {
|
||||
isku, err := models.ServerSkuManager.FetchById(guest.SkuId)
|
||||
if err != nil {
|
||||
log.Errorf("GetJsonDescAtHost sku id %s not found", guest.SkuId)
|
||||
}
|
||||
|
||||
config.InstanceType = isku.GetName()
|
||||
}
|
||||
config.InstanceType = guest.InstanceType
|
||||
|
||||
if len(guest.KeypairId) > 0 {
|
||||
config.PublicKey = guest.GetKeypairPublicKey()
|
||||
@@ -92,6 +89,15 @@ func (self *SManagedVirtualizedGuestDriver) GetJsonDescAtHost(ctx context.Contex
|
||||
config.DataDisks[i-1] = disk.DiskSize / 1024 // MB => GB
|
||||
}
|
||||
}
|
||||
|
||||
if guest.BillingType == models.BILLING_TYPE_PREPAID {
|
||||
bc, err := billing.ParseBillingCycle(guest.BillingCycle)
|
||||
if err != nil {
|
||||
log.Errorf("fail to parse billing cycle %s: %s", guest.BillingCycle, err)
|
||||
}
|
||||
config.BillingCycle = bc
|
||||
}
|
||||
|
||||
return jsonutils.Marshal(&config)
|
||||
}
|
||||
|
||||
@@ -347,6 +353,11 @@ func (self *SManagedVirtualizedGuestDriver) RequestDiskSnapshot(ctx context.Cont
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) OnGuestDeployTaskDataReceived(ctx context.Context, guest *models.SGuest, task taskman.ITask, data jsonutils.JSONObject) error {
|
||||
|
||||
recycle := false
|
||||
if guest.IsPrepaidRecycle() {
|
||||
recycle = true
|
||||
}
|
||||
|
||||
if data.Contains("disks") {
|
||||
diskInfo := make([]SDiskInfo, 0)
|
||||
err := data.Unmarshal(&diskInfo, "disks")
|
||||
@@ -367,15 +378,19 @@ func (self *SManagedVirtualizedGuestDriver) OnGuestDeployTaskDataReceived(ctx co
|
||||
disk.ExternalId = diskInfo[i].Uuid
|
||||
disk.DiskType = diskInfo[i].DiskType
|
||||
disk.Status = models.DISK_READY
|
||||
disk.BillingType = diskInfo[i].BillingType
|
||||
|
||||
disk.FsFormat = diskInfo[i].FsFromat
|
||||
if diskInfo[i].AutoDelete {
|
||||
disk.AutoDelete = true
|
||||
}
|
||||
// disk.TemplateId = diskInfo[i].TemplateId
|
||||
disk.AccessPath = diskInfo[i].Path
|
||||
disk.DiskFormat = diskInfo[i].DiskFormat
|
||||
disk.ExpiredAt = diskInfo[i].ExpiredAt
|
||||
|
||||
if !recycle {
|
||||
disk.BillingType = diskInfo[i].BillingType
|
||||
disk.ExpiredAt = diskInfo[i].ExpiredAt
|
||||
}
|
||||
|
||||
if len(diskInfo[i].Metadata) > 0 {
|
||||
for key, value := range diskInfo[i].Metadata {
|
||||
if err := disk.SetMetadata(ctx, key, value, task.GetUserCred()); err != nil {
|
||||
@@ -422,6 +437,11 @@ func (self *SManagedVirtualizedGuestDriver) OnGuestDeployTaskDataReceived(ctx co
|
||||
}
|
||||
}
|
||||
|
||||
exp, err := data.GetTime("expired_at")
|
||||
if err == nil && !guest.IsPrepaidRecycle() {
|
||||
guest.SaveRenewInfo(task.GetUserCred(), nil, &exp)
|
||||
}
|
||||
|
||||
guest.SaveDeployInfo(ctx, task.GetUserCred(), data)
|
||||
return nil
|
||||
}
|
||||
@@ -550,3 +570,15 @@ func (self *SManagedVirtualizedGuestDriver) RequestSyncConfigOnHost(ctx context.
|
||||
})
|
||||
return nil
|
||||
}*/
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) RequestRenewInstance(guest *models.SGuest, bc billing.SBillingCycle) (time.Time, error) {
|
||||
iVM, err := guest.GetIVM()
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
err = iVM.Renew(bc)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
return iVM.GetExpiredAt(), nil
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
"yunion.io/x/onecloud/pkg/util/seclib2"
|
||||
)
|
||||
|
||||
@@ -182,12 +183,16 @@ func (self *SQcloudGuestDriver) RequestDeployGuestOnHost(ctx context.Context, gu
|
||||
|
||||
var createErr error
|
||||
var iVM cloudprovider.ICloudVM
|
||||
var bc *billing.SBillingCycle
|
||||
if desc.BillingCycle.IsValid() {
|
||||
bc = &desc.BillingCycle
|
||||
}
|
||||
if len(desc.InstanceType) > 0 {
|
||||
iVM, createErr = ihost.CreateVM2(desc.Name, desc.ExternalImageId, desc.SysDiskSize, desc.InstanceType, desc.ExternalNetworkId,
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData)
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData, bc)
|
||||
} else {
|
||||
iVM, createErr = ihost.CreateVM(desc.Name, desc.ExternalImageId, desc.SysDiskSize, desc.Cpu, desc.Memory, desc.ExternalNetworkId,
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData)
|
||||
desc.IpAddr, desc.Description, passwd, desc.StorageType, desc.DataDisks, publicKey, secgroupExtId, userData, bc)
|
||||
}
|
||||
|
||||
if createErr != nil {
|
||||
@@ -387,3 +392,11 @@ func (self *SQcloudGuestDriver) RequestSyncConfigOnHost(ctx context.Context, gue
|
||||
func (self *SQcloudGuestDriver) AllowReconfigGuest() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SQcloudGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle) bool {
|
||||
months := bc.GetMonths()
|
||||
if (months >= 1 && months <= 12) || (months == 24) || (months == 36) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type SDiskInfo struct {
|
||||
@@ -85,5 +86,9 @@ func fetchIVMinfo(desc SManagedVMCreateConfig, iVM cloudprovider.ICloudVM, guest
|
||||
data.Add(jsonutils.NewString(iVM.GetGlobalId()), "uuid")
|
||||
data.Add(iVM.GetMetadata(), "metadata")
|
||||
|
||||
if iVM.GetBillingType() == models.BILLING_TYPE_PREPAID {
|
||||
data.Add(jsonutils.NewTimeString(iVM.GetExpiredAt()), "expired_at")
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -190,6 +190,14 @@ func (self *SVirtualizedGuestDriver) ValidateCreateHostData(ctx context.Context,
|
||||
return nil, httperrors.NewInvalidStatusError("Host %s is not online", bmName)
|
||||
}
|
||||
data.Add(jsonutils.NewString(host.Id), "prefer_host_id")
|
||||
if host.IsPrepaidRecycle() {
|
||||
data.Set("vmem_size", jsonutils.NewInt(int64(host.MemSize)))
|
||||
data.Set("vcpu_count", jsonutils.NewInt(int64(host.CpuCount)))
|
||||
|
||||
if host.GetGuestCount() >= 1 {
|
||||
return nil, httperrors.NewInsufficientResourceError("host has been occupied")
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -128,6 +128,11 @@ func (self *SKVMHostDriver) RequestAllocateDiskOnStorage(ctx context.Context, ho
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SKVMHostDriver) RequestRebuildDiskOnStorage(ctx context.Context, host *models.SHost, storage *models.SStorage, disk *models.SDisk, task taskman.ITask, content *jsonutils.JSONDict) error {
|
||||
content.Add(jsonutils.JSONTrue, "rebuild")
|
||||
return self.RequestAllocateDiskOnStorage(ctx, host, storage, disk, task, content)
|
||||
}
|
||||
|
||||
func (self *SKVMHostDriver) RequestDeallocateDiskOnHost(ctx context.Context, host *models.SHost, storage *models.SStorage, disk *models.SDisk, task taskman.ITask) error {
|
||||
log.Infof("Deallocating disk on host %s", host.GetName())
|
||||
header := task.GetTaskRequestHeader()
|
||||
@@ -228,11 +233,11 @@ func (self *SKVMHostDriver) PrepareConvert(host *models.SHost, image, raid strin
|
||||
return nil, err
|
||||
}
|
||||
var sysSize = "60g"
|
||||
log.Infof("%v", data)
|
||||
if data.Contains("baremetal_disk_config.0") {
|
||||
for i := 0; data.Contains(fmt.Sprintf("baremetal_disk_config.%d", i)); i++ {
|
||||
v, _ := data.Get(fmt.Sprintf("baremetal_disk_config.%d", i))
|
||||
params.Set(fmt.Sprintf("baremetal_disk_config.%d", i), v)
|
||||
jsonArray := jsonutils.GetArrayOfPrefix(data, "baremetal_disk_config")
|
||||
for i := 0; i < len(jsonArray); i += 1 { // } .Contains(fmt.Sprintf("baremetal_disk_config.%d", i)); i++ {
|
||||
// v, _ := data.Get(fmt.Sprintf("baremetal_disk_config.%d", i))
|
||||
params.Set(fmt.Sprintf("baremetal_disk_config.%d", i), jsonArray[i])
|
||||
}
|
||||
} else {
|
||||
raid, err = self.GetRaidScheme(host, raid)
|
||||
@@ -244,9 +249,10 @@ func (self *SKVMHostDriver) PrepareConvert(host *models.SHost, image, raid strin
|
||||
}
|
||||
}
|
||||
if data.Contains("disk.0") {
|
||||
for i := 0; data.Contains(fmt.Sprintf("disk.%d", i)); i++ {
|
||||
v, _ := data.Get(fmt.Sprintf("disk.%d", i))
|
||||
params.Set(fmt.Sprintf("disk.%d", i), v)
|
||||
jsonArray := jsonutils.GetArrayOfPrefix(data, "disk")
|
||||
for i := 0; i < len(jsonArray); i += 1 { // } data.Contains(fmt.Sprintf("disk.%d", i)); i++ {
|
||||
// v, _ := data.Get(fmt.Sprintf("disk.%d", i))
|
||||
params.Set(fmt.Sprintf("disk.%d", i), jsonArray[i])
|
||||
}
|
||||
} else {
|
||||
if len(image) == 0 {
|
||||
@@ -265,9 +271,10 @@ func (self *SKVMHostDriver) PrepareConvert(host *models.SHost, image, raid strin
|
||||
params.Set("disk.1", jsonutils.NewString("ext4:autoextend:/opt/cloud/workspace"))
|
||||
}
|
||||
if data.Contains("net.0") {
|
||||
for i := 0; data.Contains(fmt.Sprintf("net.%d", i)); i++ {
|
||||
v, _ := data.Get(fmt.Sprintf("net.%d", i))
|
||||
params.Set(fmt.Sprintf("net.%d", i), v)
|
||||
jsonArray := jsonutils.GetArrayOfPrefix(data, "net")
|
||||
for i := 0; i < len(jsonArray); i += 1 { // } data.Contains(fmt.Sprintf("net.%d", i)); i++ {
|
||||
// v, _ := data.Get(fmt.Sprintf("net.%d", i))
|
||||
params.Set(fmt.Sprintf("net.%d", i), jsonArray[i])
|
||||
}
|
||||
} else {
|
||||
wire := host.GetMasterWire()
|
||||
|
||||
@@ -241,6 +241,7 @@ func (self *SManagedVirtualizationHostDriver) RequestAllocateDiskOnStorage(ctx c
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewInt(int64(iDisk.GetDiskSizeMB())), "disk_size")
|
||||
data.Add(jsonutils.NewString(iDisk.GetDiskFormat()), "disk_format")
|
||||
data.Add(jsonutils.NewString(iDisk.GetAccessPath()), "disk_path")
|
||||
|
||||
return data, nil
|
||||
})
|
||||
@@ -288,3 +289,25 @@ func (self *SManagedVirtualizationHostDriver) RequestResetDisk(ctx context.Conte
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizationHostDriver) RequestRebuildDiskOnStorage(ctx context.Context, host *models.SHost, storage *models.SStorage, disk *models.SDisk, task taskman.ITask, content *jsonutils.JSONDict) error {
|
||||
iDisk, err := disk.GetIDisk()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
err := iDisk.Rebuild(ctx)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewInt(int64(iDisk.GetDiskSizeMB())), "disk_size")
|
||||
data.Add(jsonutils.NewString(iDisk.GetDiskFormat()), "disk_format")
|
||||
data.Add(jsonutils.NewString(iDisk.GetAccessPath()), "disk_path")
|
||||
|
||||
return data, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -13,8 +13,9 @@ const (
|
||||
)
|
||||
|
||||
type SBillingResourceBase struct {
|
||||
BillingType string `width:"36" charset:"ascii" nullable:"true" default:"postpaid" list:"user" create:"optional"`
|
||||
ExpiredAt time.Time `nullable:"true" list:"user" create:"optional"`
|
||||
BillingType string `width:"36" charset:"ascii" nullable:"true" default:"postpaid" list:"user" create:"admin_optional"`
|
||||
ExpiredAt time.Time `nullable:"true" list:"user" create:"admin_optional"`
|
||||
BillingCycle string `width:"10" charset:"ascii" nullable:"true" list:"user" create:"admin_optional"`
|
||||
}
|
||||
|
||||
func (self *SBillingResourceBase) GetChargeType() string {
|
||||
@@ -25,6 +26,24 @@ func (self *SBillingResourceBase) GetChargeType() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SBillingResourceBase) FetchCloudBillingInfo(info *SCloudBillingInfo) {
|
||||
info.ChargeType = self.GetChargeType()
|
||||
if self.GetChargeType() == BILLING_TYPE_PREPAID {
|
||||
info.ExpiredAt = self.ExpiredAt
|
||||
info.BillingCycle = self.BillingCycle
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SBillingResourceBase) IsValidPrePaid() bool {
|
||||
if self.BillingType == BILLING_TYPE_PREPAID {
|
||||
now := time.Now().UTC()
|
||||
if self.ExpiredAt.After(now) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type SCloudBillingInfo struct {
|
||||
Provider string
|
||||
Account string
|
||||
@@ -42,6 +61,8 @@ type SCloudBillingInfo struct {
|
||||
PriceKey string
|
||||
ChargeType string
|
||||
InternetChargeType string
|
||||
ExpiredAt time.Time
|
||||
BillingCycle string
|
||||
}
|
||||
|
||||
func MakeCloudBillingInfo(region *SCloudregion, zone *SZone, provider *SCloudprovider) SCloudBillingInfo {
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -13,8 +15,6 @@ import (
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"net/url"
|
||||
"strconv"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
|
||||
+60
-13
@@ -28,6 +28,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -113,14 +114,31 @@ func (manager *SDiskManager) GetContextManager() []db.IModelManager {
|
||||
}
|
||||
|
||||
func (manager *SDiskManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
||||
queryDict, ok := query.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid querystring format")
|
||||
}
|
||||
|
||||
billingTypeStr, _ := queryDict.GetString("billing_type")
|
||||
if len(billingTypeStr) > 0 {
|
||||
if billingTypeStr == BILLING_TYPE_POSTPAID {
|
||||
q = q.Filter(
|
||||
sqlchemy.OR(
|
||||
sqlchemy.IsNullOrEmpty(q.Field("billing_type")),
|
||||
sqlchemy.Equals(q.Field("billing_type"), billingTypeStr),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
q = q.Equals("billing_type", billingTypeStr)
|
||||
}
|
||||
queryDict.Remove("billing_type")
|
||||
}
|
||||
|
||||
q, err := manager.SSharableVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
queryDict, ok := query.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Invalid querystring formst: %v", query)
|
||||
}
|
||||
|
||||
if query.Contains("unused") {
|
||||
guestdisks := GuestdiskManager.Query().SubQuery()
|
||||
sq := guestdisks.Query(guestdisks.Field("disk_id"))
|
||||
@@ -435,9 +453,10 @@ func (self *SDisk) StartAllocate(ctx context.Context, host *SHost, storage *SSto
|
||||
}
|
||||
}
|
||||
if rebuild {
|
||||
content.Add(jsonutils.JSONTrue, "rebuild")
|
||||
return host.GetHostDriver().RequestRebuildDiskOnStorage(ctx, host, storage, self, task, content)
|
||||
} else {
|
||||
return host.GetHostDriver().RequestAllocateDiskOnStorage(ctx, host, storage, self, task, content)
|
||||
}
|
||||
return host.GetHostDriver().RequestAllocateDiskOnStorage(ctx, host, storage, self, task, content)
|
||||
}
|
||||
|
||||
func (self *SDisk) AllowGetDetailsConvertSnapshot(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
@@ -843,9 +862,14 @@ func (manager *SDiskManager) SyncDisks(ctx context.Context, userCred mcclient.To
|
||||
}
|
||||
|
||||
func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.TokenCredential, extDisk cloudprovider.ICloudDisk, index int, projectId string, projectSync bool) error {
|
||||
recycle := false
|
||||
guests := self.GetGuests()
|
||||
if len(guests) == 1 && guests[0].IsPrepaidRecycle() {
|
||||
recycle = true
|
||||
}
|
||||
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
extDisk.Refresh()
|
||||
self.Name = extDisk.GetName()
|
||||
// self.Name = extDisk.GetName()
|
||||
self.Status = extDisk.GetStatus()
|
||||
self.DiskFormat = extDisk.GetDiskFormat()
|
||||
self.DiskSize = extDisk.GetDiskSizeMB()
|
||||
@@ -863,10 +887,12 @@ func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.Toke
|
||||
|
||||
self.IsEmulated = extDisk.IsEmulated()
|
||||
|
||||
self.BillingType = extDisk.GetBillingType()
|
||||
self.ExpiredAt = extDisk.GetExpiredAt()
|
||||
if !recycle {
|
||||
self.BillingType = extDisk.GetBillingType()
|
||||
self.ExpiredAt = extDisk.GetExpiredAt()
|
||||
}
|
||||
|
||||
self.ProjectId = userCred.GetProjectId()
|
||||
// self.ProjectId = userCred.GetProjectId()
|
||||
if projectSync && len(projectId) > 0 {
|
||||
self.ProjectId = projectId
|
||||
}
|
||||
@@ -1325,7 +1351,7 @@ func (self *SDisk) GetShortDesc() *jsonutils.JSONDict {
|
||||
billingInfo.PriceKey = priceKey
|
||||
}
|
||||
|
||||
billingInfo.ChargeType = self.GetChargeType()
|
||||
self.FetchCloudBillingInfo(&billingInfo)
|
||||
|
||||
desc.Update(jsonutils.Marshal(billingInfo))
|
||||
|
||||
@@ -1376,7 +1402,7 @@ func (manager *SDiskManager) getExpiredPendingDeleteDisks() []SDisk {
|
||||
return disks
|
||||
}
|
||||
|
||||
func (manager *SDiskManager) CleanPendingDeleteDisks(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
func (manager *SDiskManager) CleanPendingDeleteDisks(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
disks := manager.getExpiredPendingDeleteDisks()
|
||||
if disks == nil {
|
||||
return
|
||||
@@ -1396,7 +1422,7 @@ func (manager *SDiskManager) getAutoSnapshotDisks() []SDisk {
|
||||
return dest
|
||||
}
|
||||
|
||||
func (manager *SDiskManager) AutoDiskSnapshot(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
func (manager *SDiskManager) AutoDiskSnapshot(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
disks := manager.getAutoSnapshotDisks()
|
||||
if disks == nil {
|
||||
return
|
||||
@@ -1435,3 +1461,24 @@ func (disk *SDisk) StratCreateBackupTask(ctx context.Context, userCred mcclient.
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDisk) SaveRenewInfo(userCred mcclient.TokenCredential, bc *billing.SBillingCycle, expireAt *time.Time) error {
|
||||
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
if self.BillingType != BILLING_TYPE_PREPAID {
|
||||
self.BillingType = BILLING_TYPE_PREPAID
|
||||
}
|
||||
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("Update error %s", err)
|
||||
return err
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_RENEW, self.GetShortDesc(), userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -827,30 +827,62 @@ func (u EipUsage) Total() int {
|
||||
return u.PublicIPCount + u.EIPCount
|
||||
}
|
||||
|
||||
func (manager *SElasticipManager) usageQ(q *sqlchemy.SQuery, rangeObj db.IStandaloneModel, hostTypes []string) *sqlchemy.SQuery {
|
||||
if rangeObj == nil {
|
||||
func (manager *SElasticipManager) usageQByProvider(q *sqlchemy.SQuery, providers []string) *sqlchemy.SQuery {
|
||||
if len(providers) == 0 {
|
||||
return q
|
||||
}
|
||||
zones := ZoneManager.Query().SubQuery()
|
||||
hosts := HostManager.Query().SubQuery()
|
||||
sq := zones.Query(zones.Field("cloudregion_id")).
|
||||
Join(hosts, sqlchemy.AND(
|
||||
sqlchemy.IsFalse(hosts.Field("deleted")),
|
||||
sqlchemy.IsTrue(hosts.Field("enabled")),
|
||||
sqlchemy.Equals(hosts.Field("zone_id"), zones.Field("id"))))
|
||||
sq = AttachUsageQuery(sq, hosts, hosts.Field("id"), hostTypes, rangeObj)
|
||||
q = q.Filter(sqlchemy.In(q.Field("cloudregion_id"), sq.Distinct()))
|
||||
cloudproviders := CloudproviderManager.Query().SubQuery()
|
||||
subq := cloudproviders.Query(cloudproviders.Field("id")).In("provider", providers).SubQuery()
|
||||
q = q.Filter(sqlchemy.In(q.Field("manager_id"), subq))
|
||||
return q
|
||||
}
|
||||
|
||||
func (manager *SElasticipManager) TotalCount(projectId string, rangeObj db.IStandaloneModel, hostTypes []string) EipUsage {
|
||||
func (manager *SElasticipManager) usageQByRange(q *sqlchemy.SQuery, rangeObj db.IStandaloneModel) *sqlchemy.SQuery {
|
||||
if rangeObj == nil {
|
||||
return q
|
||||
}
|
||||
|
||||
kw := rangeObj.Keyword()
|
||||
// log.Debugf("rangeObj keyword: %s", kw)
|
||||
switch kw {
|
||||
case "zone":
|
||||
zone := rangeObj.(*SZone)
|
||||
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), zone.CloudregionId))
|
||||
case "wire":
|
||||
wire := rangeObj.(*SWire)
|
||||
zone := wire.GetZone()
|
||||
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), zone.CloudregionId))
|
||||
case "host":
|
||||
host := rangeObj.(*SHost)
|
||||
zone := host.GetZone()
|
||||
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), zone.CloudregionId))
|
||||
case "cloudprovider":
|
||||
q = q.Filter(sqlchemy.Equals(q.Field("manager_id"), rangeObj.GetId()))
|
||||
case "cloudaccount":
|
||||
cloudproviders := CloudproviderManager.Query().SubQuery()
|
||||
subq := cloudproviders.Query(cloudproviders.Field("id")).Equals("cloudaccount_id", rangeObj.GetId()).SubQuery()
|
||||
q = q.Filter(sqlchemy.In(q.Field("manager_id"), subq))
|
||||
case "cloudregion":
|
||||
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), rangeObj.GetId()))
|
||||
}
|
||||
|
||||
return q
|
||||
}
|
||||
|
||||
func (manager *SElasticipManager) usageQ(q *sqlchemy.SQuery, rangeObj db.IStandaloneModel, providers []string) *sqlchemy.SQuery {
|
||||
q = manager.usageQByRange(q, rangeObj)
|
||||
q = manager.usageQByProvider(q, providers)
|
||||
return q
|
||||
}
|
||||
|
||||
func (manager *SElasticipManager) TotalCount(projectId string, rangeObj db.IStandaloneModel, providers []string) EipUsage {
|
||||
usage := EipUsage{}
|
||||
q1 := manager.Query().Equals("mode", EIP_MODE_INSTANCE_PUBLICIP)
|
||||
q1 = manager.usageQ(q1, rangeObj, hostTypes)
|
||||
q1 = manager.usageQ(q1, rangeObj, providers)
|
||||
q2 := manager.Query().Equals("mode", EIP_MODE_STANDALONE_EIP)
|
||||
q2 = manager.usageQ(q2, rangeObj, hostTypes)
|
||||
q2 = manager.usageQ(q2, rangeObj, providers)
|
||||
q3 := manager.Query().Equals("mode", EIP_MODE_STANDALONE_EIP).IsNotEmpty("associate_id")
|
||||
q3 = manager.usageQ(q3, rangeObj, hostTypes)
|
||||
q3 = manager.usageQ(q3, rangeObj, providers)
|
||||
if len(projectId) > 0 {
|
||||
q1 = q1.Equals("tenant_id", projectId)
|
||||
q2 = q2.Equals("tenant_id", projectId)
|
||||
|
||||
@@ -22,8 +22,10 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
"yunion.io/x/onecloud/pkg/util/seclib2"
|
||||
|
||||
"time"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
"yunion.io/x/pkg/util/fileutils"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
@@ -776,23 +778,19 @@ func (self *SGuest) AllowPerformRebuildRoot(ctx context.Context, userCred mcclie
|
||||
|
||||
func (self *SGuest) PerformRebuildRoot(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
imageId, _ := data.GetString("image_id")
|
||||
if len(imageId) == 0 {
|
||||
gdc := self.CategorizeDisks()
|
||||
imageId = gdc.Root.GetTemplateId()
|
||||
if len(imageId) == 0 {
|
||||
return nil, httperrors.NewBadRequestError("No template for root disk")
|
||||
|
||||
if len(imageId) > 0 {
|
||||
img, err := CachedimageManager.getImageInfo(ctx, userCred, imageId, false)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewNotFoundError("failed to find %s", imageId)
|
||||
}
|
||||
osType, _ := img.Properties["os_type"]
|
||||
osName := self.GetMetadata("os_name", userCred)
|
||||
if len(osName) == 0 && len(osType) == 0 && strings.ToLower(osType) != strings.ToLower(osName) {
|
||||
return nil, httperrors.NewBadRequestError("Cannot switch OS between %s-%s", osName, osType)
|
||||
}
|
||||
imageId = img.Id
|
||||
}
|
||||
img, err := CachedimageManager.getImageInfo(ctx, userCred, imageId, false)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewNotFoundError("failed to find %s", imageId)
|
||||
}
|
||||
osType, _ := img.Properties["os_type"]
|
||||
osName := self.GetMetadata("os_name", userCred)
|
||||
if len(osName) == 0 && len(osType) == 0 && strings.ToLower(osType) != strings.ToLower(osName) {
|
||||
return nil, httperrors.NewBadRequestError("Cannot switch OS between %s-%s", osName, osType)
|
||||
}
|
||||
imageId = img.Id
|
||||
|
||||
rebuildStatus, err := self.GetDriver().GetRebuildRootStatus()
|
||||
if err != nil {
|
||||
@@ -834,11 +832,20 @@ func (self *SGuest) PerformRebuildRoot(ctx context.Context, userCred mcclient.To
|
||||
}
|
||||
}
|
||||
|
||||
return nil, self.StartRebuildRootTask(ctx, userCred, imageId, needStop, autoStart, passwd, resetPasswd)
|
||||
allDisks := jsonutils.QueryBoolean(data, "all_disks", false)
|
||||
|
||||
return nil, self.StartRebuildRootTask(ctx, userCred, imageId, needStop, autoStart, passwd, resetPasswd, allDisks)
|
||||
}
|
||||
|
||||
func (self *SGuest) StartRebuildRootTask(ctx context.Context, userCred mcclient.TokenCredential, imageId string, needStop, autoStart bool, passwd string, resetPasswd bool) error {
|
||||
func (self *SGuest) StartRebuildRootTask(ctx context.Context, userCred mcclient.TokenCredential, imageId string, needStop, autoStart bool, passwd string, resetPasswd bool, allDisk bool) error {
|
||||
data := jsonutils.NewDict()
|
||||
if len(imageId) == 0 {
|
||||
gdc := self.CategorizeDisks()
|
||||
imageId = gdc.Root.GetTemplateId()
|
||||
if len(imageId) == 0 {
|
||||
return httperrors.NewBadRequestError("No template for root disk")
|
||||
}
|
||||
}
|
||||
data.Set("image_id", jsonutils.NewString(imageId))
|
||||
if needStop {
|
||||
data.Set("need_stop", jsonutils.JSONTrue)
|
||||
@@ -854,6 +861,12 @@ func (self *SGuest) StartRebuildRootTask(ctx context.Context, userCred mcclient.
|
||||
if len(passwd) > 0 {
|
||||
data.Set("password", jsonutils.NewString(passwd))
|
||||
}
|
||||
|
||||
if allDisk {
|
||||
data.Set("all_disks", jsonutils.JSONTrue)
|
||||
} else {
|
||||
data.Set("all_disks", jsonutils.JSONFalse)
|
||||
}
|
||||
if self.GetHypervisor() == HYPERVISOR_BAREMETAL {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "BaremetalServerRebuildRootTask", self, userCred, data, "", "", nil)
|
||||
if err != nil {
|
||||
@@ -882,13 +895,18 @@ func (self *SGuest) AllowPerformCreatedisk(ctx context.Context, userCred mcclien
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
var diskIdx, diskSize = 0, 0
|
||||
diskSize := 0
|
||||
disksConf := jsonutils.NewDict()
|
||||
diskSizes := make(map[string]int, 0)
|
||||
diskSeq := fmt.Sprintf("disk.%d", diskIdx)
|
||||
for data.Contains(diskSeq) {
|
||||
diskDef, _ := data.Get(diskSeq)
|
||||
diskInfo, err := parseDiskInfo(ctx, userCred, diskDef)
|
||||
|
||||
diskDefArray := jsonutils.GetArrayOfPrefix(data, "disk")
|
||||
if len(diskDefArray) == 0 {
|
||||
logclient.AddActionLog(self, logclient.ACT_CREATE, "No Disk Info Provided", userCred, false)
|
||||
return nil, httperrors.NewBadRequestError("No Disk Info Provided")
|
||||
}
|
||||
|
||||
for diskIdx := 0; diskIdx < len(diskDefArray); diskIdx += 1 {
|
||||
diskInfo, err := parseDiskInfo(ctx, userCred, diskDefArray[diskIdx])
|
||||
if err != nil {
|
||||
logclient.AddActionLog(self, logclient.ACT_CREATE, err.Error(), userCred, false)
|
||||
return nil, httperrors.NewBadRequestError(err.Error())
|
||||
@@ -896,19 +914,13 @@ func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.Tok
|
||||
if len(diskInfo.Backend) == 0 {
|
||||
diskInfo.Backend = self.getDefaultStorageType()
|
||||
}
|
||||
disksConf.Set(diskSeq, jsonutils.Marshal(diskInfo))
|
||||
disksConf.Set(fmt.Sprintf("disk.%d", diskIdx), jsonutils.Marshal(diskInfo))
|
||||
if _, ok := diskSizes[diskInfo.Backend]; !ok {
|
||||
diskSizes[diskInfo.Backend] = diskInfo.SizeMb
|
||||
} else {
|
||||
diskSizes[diskInfo.Backend] += diskInfo.SizeMb
|
||||
}
|
||||
diskSize += diskInfo.SizeMb
|
||||
diskIdx += 1
|
||||
diskSeq = fmt.Sprintf("disk.%d", diskIdx)
|
||||
}
|
||||
if diskIdx == 0 {
|
||||
logclient.AddActionLog(self, logclient.ACT_CREATE, "No Disk Info Provided", userCred, false)
|
||||
return nil, httperrors.NewBadRequestError("No Disk Info Provided")
|
||||
}
|
||||
host := self.GetHost()
|
||||
if host == nil {
|
||||
@@ -938,7 +950,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)
|
||||
err = self.CreateDisksOnHost(ctx, userCred, host, disksConf, pendingUsage, false)
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, self.ProjectId, nil, pendingUsage)
|
||||
logclient.AddActionLog(self, logclient.ACT_CREATE, err.Error(), userCred, false)
|
||||
@@ -1220,14 +1232,12 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
|
||||
var addCpu, addMem int
|
||||
confs := jsonutils.NewDict()
|
||||
skuId, _ := data.GetString("sku_id")
|
||||
if len(skuId) > 0 && self.SkuId != skuId {
|
||||
isku, err := ServerSkuManager.FetchById(skuId)
|
||||
skuId := jsonutils.GetAnyString(data, []string{"instance_type", "sku", "flavor"})
|
||||
if len(skuId) > 0 {
|
||||
sku, err := ServerSkuManager.FetchSkuByNameAndHypervisor(skuId, self.GetHypervisor(), true)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewNotFoundError("sku_id %s not found", skuId)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sku := isku.(*SServerSku)
|
||||
addCpu = sku.CpuCoreCount - int(self.VcpuCount)
|
||||
addMem = sku.MemorySizeMB - self.VmemSize
|
||||
confs.Add(jsonutils.NewString(sku.ExternalId), "sku_id")
|
||||
@@ -1245,6 +1255,9 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
return nil, httperrors.NewBadRequestError("Params vcpu_count parse error")
|
||||
}
|
||||
addCpu = int(nVcpu - int64(self.VcpuCount))
|
||||
if addCpu < 0 {
|
||||
addCpu = 0
|
||||
}
|
||||
}
|
||||
vmemSize, err := data.GetString("vmem_size")
|
||||
if err == nil {
|
||||
@@ -1260,6 +1273,9 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
return nil, httperrors.NewBadRequestError("Params vmem_size parse error")
|
||||
}
|
||||
addMem = nVmem - self.VmemSize
|
||||
if addMem < 0 {
|
||||
addMem = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1273,7 +1289,7 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
for {
|
||||
diskNum := fmt.Sprintf("disk.%d", diskIdx)
|
||||
diskDesc, err := data.Get(diskNum)
|
||||
if err != nil {
|
||||
if err != nil || diskDesc == jsonutils.JSONNull {
|
||||
break
|
||||
}
|
||||
diskConf, err := parseDiskInfo(ctx, userCred, diskDesc)
|
||||
@@ -1319,11 +1335,6 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
}
|
||||
|
||||
provider, e := self.GetHost().GetDriver()
|
||||
/*if e != nil {
|
||||
log.Errorf("Get Provider Error: %s", e)
|
||||
return nil, httperrors.NewInsufficientResourceError("Provider Not Found")
|
||||
}*/
|
||||
|
||||
if e != nil || !provider.IsPublicCloud() {
|
||||
for storageId, needSize := range diskSizes {
|
||||
iStorage, err := StorageManager.FetchById(storageId)
|
||||
@@ -1368,7 +1379,7 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
}
|
||||
}
|
||||
if newDisks.Length() > 0 {
|
||||
err := self.CreateDisksOnHost(ctx, userCred, host, newDisks, pendingUsage)
|
||||
err := self.CreateDisksOnHost(ctx, userCred, host, newDisks, pendingUsage, false)
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, self.ProjectId, nil, pendingUsage)
|
||||
return nil, httperrors.NewBadRequestError("Create disk on host error: %s", err)
|
||||
@@ -1389,15 +1400,31 @@ func (self *SGuest) StartChangeConfigTask(ctx context.Context, userCred mcclient
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) revokeAllSecgroups(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
err := self.revokeSecgroup(ctx, userCred, self.getSecgroup())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = GuestsecgroupManager.DeleteGuestSecgroup(ctx, userCred, self, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) DoPendingDelete(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
eip, _ := self.GetEip()
|
||||
if eip != nil {
|
||||
eip.DoPendingDelete(ctx, userCred)
|
||||
}
|
||||
// revoke all secgroups
|
||||
// TODO: sync revoked secgroups to remote cloud
|
||||
self.revokeAllSecgroups(ctx, userCred)
|
||||
// remove detachable disks
|
||||
for _, guestdisk := range self.GetDisks() {
|
||||
disk := guestdisk.GetDisk()
|
||||
storage := disk.GetStorage()
|
||||
if utils.IsInStringArray(storage.StorageType, STORAGE_LOCAL_TYPES) || utils.IsInStringArray(disk.DiskType, []string{DISK_TYPE_SYS, DISK_TYPE_SWAP}) || (utils.IsInStringArray(self.Hypervisor, PUBLIC_CLOUD_HYPERVISORS) && disk.AutoDelete) {
|
||||
if storage.IsLocal() || disk.BillingType == BILLING_TYPE_PREPAID || utils.IsInStringArray(disk.DiskType, []string{DISK_TYPE_SYS, DISK_TYPE_SWAP}) || (utils.IsInStringArray(self.Hypervisor, PUBLIC_CLOUD_HYPERVISORS) && disk.AutoDelete) {
|
||||
disk.DoPendingDelete(ctx, userCred)
|
||||
} else {
|
||||
self.DetachDisk(ctx, disk, userCred)
|
||||
@@ -2007,3 +2034,81 @@ func (self *SGuest) PerformDelExtraOption(ctx context.Context, userCred mcclient
|
||||
extraOptions.Remove(key)
|
||||
return nil, self.SetExtraOptions(ctx, userCred, extraOptions)
|
||||
}
|
||||
|
||||
func (self *SGuest) AllowPerformRenew(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowPerform(userCred, self, "renew")
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformRenew(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
durationStr := jsonutils.GetAnyString(data, []string{"duration"})
|
||||
if len(durationStr) == 0 {
|
||||
return nil, httperrors.NewInputParameterError("missong duration")
|
||||
}
|
||||
|
||||
bc, err := billing.ParseBillingCycle(durationStr)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid duration %s: %s", durationStr, err)
|
||||
}
|
||||
|
||||
if !self.GetDriver().IsSupportedBillingCycle(bc) {
|
||||
return nil, httperrors.NewInputParameterError("unsupported duration %s", durationStr)
|
||||
}
|
||||
|
||||
err = self.startGuestRenewTask(ctx, userCred, durationStr, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) startGuestRenewTask(ctx context.Context, userCred mcclient.TokenCredential, duration string, parentTaskId string) error {
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewString(duration), "duration")
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestRenewTask", self, userCred, data, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("fail to crate GuestRenewTask %s", err)
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) SaveRenewInfo(userCred mcclient.TokenCredential, bc *billing.SBillingCycle, expireAt *time.Time) error {
|
||||
err := self.doSaveRenewInfo(userCred, bc, expireAt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
guestdisks := self.GetDisks()
|
||||
for i := 0; i < len(guestdisks); i += 1 {
|
||||
disk := guestdisks[i].GetDisk()
|
||||
if disk.BillingType == BILLING_TYPE_PREPAID {
|
||||
err = disk.SaveRenewInfo(userCred, bc, expireAt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) doSaveRenewInfo(userCred mcclient.TokenCredential, bc *billing.SBillingCycle, expireAt *time.Time) error {
|
||||
_, err := self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
if self.BillingType != BILLING_TYPE_PREPAID {
|
||||
self.BillingType = BILLING_TYPE_PREPAID
|
||||
}
|
||||
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(), userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,11 +3,13 @@ package models
|
||||
import (
|
||||
"context"
|
||||
|
||||
"time"
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
type IGuestDriver interface {
|
||||
@@ -17,6 +19,10 @@ type IGuestDriver interface {
|
||||
GetMaxVMemSizeGB() int
|
||||
GetMaxSecurityGroupCount() int
|
||||
|
||||
IsSupportedBillingCycle(bc billing.SBillingCycle) bool
|
||||
|
||||
RequestRenewInstance(guest *SGuest, bc billing.SBillingCycle) (time.Time, error)
|
||||
|
||||
GetJsonDescAtHost(ctx context.Context, guest *SGuest, host *SHost) jsonutils.JSONObject
|
||||
|
||||
ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
|
||||
|
||||
+364
-182
@@ -22,6 +22,7 @@ import (
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
@@ -31,6 +32,7 @@ import (
|
||||
"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/billing"
|
||||
"yunion.io/x/onecloud/pkg/util/seclib2"
|
||||
)
|
||||
|
||||
@@ -125,21 +127,36 @@ const (
|
||||
HYPERVISOR_BAREMETAL = "baremetal"
|
||||
HYPERVISOR_ESXI = "esxi"
|
||||
HYPERVISOR_HYPERV = "hyperv"
|
||||
HYPERVISOR_ALIYUN = "aliyun"
|
||||
HYPERVISOR_QCLOUD = "qcloud"
|
||||
HYPERVISOR_AZURE = "azure"
|
||||
HYPERVISOR_AWS = "aws"
|
||||
HYPERVISOR_XEN = "xen"
|
||||
|
||||
HYPERVISOR_ALIYUN = "aliyun"
|
||||
HYPERVISOR_QCLOUD = "qcloud"
|
||||
HYPERVISOR_AZURE = "azure"
|
||||
HYPERVISOR_AWS = "aws"
|
||||
|
||||
// HYPERVISOR_DEFAULT = HYPERVISOR_KVM
|
||||
HYPERVISOR_DEFAULT = HYPERVISOR_ALIYUN
|
||||
HYPERVISOR_DEFAULT = HYPERVISOR_KVM
|
||||
)
|
||||
|
||||
var VM_RUNNING_STATUS = []string{VM_START_START, VM_STARTING, VM_RUNNING, VM_BLOCK_STREAM}
|
||||
var VM_CREATING_STATUS = []string{VM_CREATE_NETWORK, VM_CREATE_DISK, VM_START_DEPLOY, VM_DEPLOYING}
|
||||
|
||||
var HYPERVISORS = []string{HYPERVISOR_KVM, HYPERVISOR_BAREMETAL, HYPERVISOR_ESXI, HYPERVISOR_CONTAINER, HYPERVISOR_ALIYUN, HYPERVISOR_AZURE, HYPERVISOR_AWS, HYPERVISOR_QCLOUD}
|
||||
var HYPERVISORS = []string{HYPERVISOR_KVM,
|
||||
HYPERVISOR_BAREMETAL,
|
||||
HYPERVISOR_ESXI,
|
||||
HYPERVISOR_CONTAINER,
|
||||
HYPERVISOR_ALIYUN,
|
||||
HYPERVISOR_AZURE,
|
||||
HYPERVISOR_AWS,
|
||||
HYPERVISOR_QCLOUD,
|
||||
}
|
||||
|
||||
var PUBLIC_CLOUD_HYPERVISORS = []string{HYPERVISOR_ALIYUN, HYPERVISOR_AWS, HYPERVISOR_AZURE, HYPERVISOR_QCLOUD}
|
||||
var PUBLIC_CLOUD_HYPERVISORS = []string{
|
||||
HYPERVISOR_ALIYUN,
|
||||
HYPERVISOR_AWS,
|
||||
HYPERVISOR_AZURE,
|
||||
HYPERVISOR_QCLOUD,
|
||||
}
|
||||
|
||||
// var HYPERVISORS = []string{HYPERVISOR_ALIYUN}
|
||||
|
||||
@@ -214,7 +231,7 @@ type SGuest struct {
|
||||
|
||||
Hypervisor string `width:"16" charset:"ascii" nullable:"false" default:"kvm" list:"user" create:"required"` // Column(VARCHAR(16, charset='ascii'), nullable=False, default=HYPERVISOR_DEFAULT)
|
||||
|
||||
SkuId string `width:"64" charset:"ascii" nullable:"true" list:"user" create:"optional"`
|
||||
InstanceType string `width:"64" charset:"ascii" nullable:"true" list:"user" create:"optional"`
|
||||
}
|
||||
|
||||
func (manager *SGuestManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
@@ -227,14 +244,30 @@ func (manager *SGuestManager) AllowListItems(ctx context.Context, userCred mccli
|
||||
}
|
||||
|
||||
func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
queryDict, ok := query.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid querystring format")
|
||||
}
|
||||
|
||||
billingTypeStr, _ := queryDict.GetString("billing_type")
|
||||
if len(billingTypeStr) > 0 {
|
||||
if billingTypeStr == BILLING_TYPE_POSTPAID {
|
||||
q = q.Filter(
|
||||
sqlchemy.OR(
|
||||
sqlchemy.IsNullOrEmpty(q.Field("billing_type")),
|
||||
sqlchemy.Equals(q.Field("billing_type"), billingTypeStr),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
q = q.Equals("billing_type", billingTypeStr)
|
||||
}
|
||||
queryDict.Remove("billing_type")
|
||||
}
|
||||
|
||||
q, err := manager.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
isBMstr, _ := queryDict.GetString("baremetal")
|
||||
if len(isBMstr) > 0 && utils.ToBool(isBMstr) {
|
||||
queryDict.Add(jsonutils.NewString(HYPERVISOR_BAREMETAL), "hypervisor")
|
||||
@@ -245,6 +278,25 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
|
||||
q = q.Equals("hypervisor", hypervisor)
|
||||
}
|
||||
|
||||
resourceTypeStr := jsonutils.GetAnyString(queryDict, []string{"resource_type"})
|
||||
if len(resourceTypeStr) > 0 {
|
||||
hosts := HostManager.Query().SubQuery()
|
||||
subq := hosts.Query(hosts.Field("id"))
|
||||
switch resourceTypeStr {
|
||||
case HostResourceTypeShared:
|
||||
subq = subq.Filter(
|
||||
sqlchemy.OR(
|
||||
sqlchemy.IsNullOrEmpty(hosts.Field("resource_type")),
|
||||
sqlchemy.Equals(hosts.Field("resource_type"), resourceTypeStr),
|
||||
),
|
||||
)
|
||||
default:
|
||||
subq = subq.Equals("resource_type", resourceTypeStr)
|
||||
}
|
||||
|
||||
q = q.In("host_id", subq.SubQuery())
|
||||
}
|
||||
|
||||
hostFilter, _ := queryDict.GetString("host")
|
||||
if len(hostFilter) > 0 {
|
||||
host, _ := HostManager.FetchByIdOrName(nil, hostFilter)
|
||||
@@ -320,26 +372,17 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
|
||||
}
|
||||
disk := diskI.(*SDisk)
|
||||
guestdisks := GuestdiskManager.Query().SubQuery()
|
||||
count := guestdisks.Query().Filter(sqlchemy.AND(
|
||||
sqlchemy.Equals(guestdisks.Field("disk_id"), disk.Id),
|
||||
sqlchemy.IsFalse(guestdisks.Field("deleted")))).Count()
|
||||
count := guestdisks.Query().Equals("disk_id", disk.Id).Count()
|
||||
if count > 0 {
|
||||
sgq := guestdisks.Query(guestdisks.Field("guest_id")).
|
||||
Filter(sqlchemy.AND(
|
||||
sqlchemy.Equals(guestdisks.Field("disk_id"), disk.Id),
|
||||
sqlchemy.IsFalse(guestdisks.Field("deleted"))))
|
||||
sgq := guestdisks.Query(guestdisks.Field("guest_id")).Equals("disk_id", disk.Id).SubQuery()
|
||||
q = q.Filter(sqlchemy.In(q.Field("id"), sgq))
|
||||
} else {
|
||||
hosts := HostManager.Query().SubQuery()
|
||||
hoststorages := HoststorageManager.Query().SubQuery()
|
||||
storages := StorageManager.Query().SubQuery()
|
||||
sq := hosts.Query(hosts.Field("id")).
|
||||
Join(hoststorages, sqlchemy.AND(
|
||||
sqlchemy.Equals(hoststorages.Field("host_id"), hosts.Field("id")),
|
||||
sqlchemy.IsFalse(hoststorages.Field("deleted")))).
|
||||
Join(storages, sqlchemy.AND(
|
||||
sqlchemy.Equals(storages.Field("id"), hoststorages.Field("storage_id")),
|
||||
sqlchemy.IsFalse(storages.Field("deleted")))).
|
||||
Join(hoststorages, sqlchemy.Equals(hoststorages.Field("host_id"), hosts.Field("id"))).
|
||||
Join(storages, sqlchemy.Equals(storages.Field("id"), hoststorages.Field("storage_id"))).
|
||||
Filter(sqlchemy.Equals(storages.Field("id"), disk.StorageId)).SubQuery()
|
||||
q = q.In("host_id", sq)
|
||||
}
|
||||
@@ -440,7 +483,10 @@ func (guest *SGuest) GetDriver() IGuestDriver {
|
||||
|
||||
func (guest *SGuest) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if guest.DisableDelete.IsTrue() {
|
||||
return fmt.Errorf("Virtual server is locked, cannot delete")
|
||||
return httperrors.NewInvalidStatusError("Virtual server is locked, cannot delete")
|
||||
}
|
||||
if guest.IsValidPrePaid() {
|
||||
return httperrors.NewForbiddenError("not allow to delete prepaid server in valid status")
|
||||
}
|
||||
return guest.SVirtualResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
@@ -579,16 +625,6 @@ func validateMemCpuData(data jsonutils.JSONObject) (int, int, error) {
|
||||
return vmemSize, vcpuCount, nil
|
||||
}
|
||||
|
||||
func validateSkuData(sku_id string) (string, int, int, error) {
|
||||
isku, err := ServerSkuManager.FetchById(sku_id)
|
||||
if err != nil {
|
||||
return "", 0, 0, err
|
||||
}
|
||||
|
||||
sku := isku.(*SServerSku)
|
||||
return sku.GetId(), sku.CpuCoreCount, sku.MemorySizeMB, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
vmemSize, vcpuCount, err := validateMemCpuData(data)
|
||||
if err != nil {
|
||||
@@ -644,8 +680,9 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
var osProf osprofile.SOSProfile
|
||||
hypervisor, _ = data.GetString("hypervisor")
|
||||
if hypervisor != HYPERVISOR_CONTAINER {
|
||||
|
||||
disk0Json, _ := data.Get("disk.0")
|
||||
if disk0Json == nil {
|
||||
if disk0Json == nil || disk0Json == jsonutils.JSONNull {
|
||||
return nil, httperrors.NewInputParameterError("No disk information provided")
|
||||
}
|
||||
diskConfig, err := parseDiskInfo(ctx, userCred, disk0Json)
|
||||
@@ -681,14 +718,62 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
data.Add(jsonutils.NewString(osProf.OSType), "os_type")
|
||||
}
|
||||
data.Add(jsonutils.Marshal(osProf), "__os_profile__")
|
||||
}
|
||||
|
||||
data, err = ValidateScheduleCreateData(ctx, userCred, data, hypervisor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hypervisor, _ = data.GetString("hypervisor")
|
||||
if hypervisor != HYPERVISOR_CONTAINER {
|
||||
// support sku here
|
||||
var sku *SServerSku
|
||||
skuId := jsonutils.GetAnyString(data, []string{"sku", "flavor", "instance_type"})
|
||||
if len(skuId) > 0 {
|
||||
sku, err := ServerSkuManager.FetchSkuByNameAndHypervisor(skuId, hypervisor, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data.Add(jsonutils.NewString(sku.Id), "instance_type")
|
||||
data.Add(jsonutils.NewInt(int64(sku.MemorySizeMB)), "vmem_size")
|
||||
data.Add(jsonutils.NewInt(int64(sku.CpuCoreCount)), "vcpu_count")
|
||||
} else {
|
||||
vmemSize, vcpuCount, err := validateMemCpuData(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if vmemSize == 0 {
|
||||
return nil, httperrors.NewInputParameterError("Missing memory size")
|
||||
}
|
||||
if vcpuCount == 0 {
|
||||
vcpuCount = 1
|
||||
}
|
||||
data.Add(jsonutils.NewInt(int64(vmemSize)), "vmem_size")
|
||||
data.Add(jsonutils.NewInt(int64(vcpuCount)), "vcpu_count")
|
||||
}
|
||||
|
||||
dataDiskDefs := make([]string, 0)
|
||||
if sku != nil && sku.AttachedDiskCount > 0 {
|
||||
for i := 0; i < sku.AttachedDiskCount; i += 1 {
|
||||
dataDiskDefs = append(dataDiskDefs, fmt.Sprintf("%dgb:%s", sku.AttachedDiskSizeGB, sku.AttachedDiskType))
|
||||
}
|
||||
}
|
||||
|
||||
// start from data disk
|
||||
for idx := 1; data.Contains(fmt.Sprintf("disk.%d", idx)); idx += 1 {
|
||||
diskJson, err := data.Get(fmt.Sprintf("disk.%d", idx))
|
||||
jsonArray := jsonutils.GetArrayOfPrefix(data, "disk")
|
||||
for idx := 1; idx < len(jsonArray); idx += 1 { // data.Contains(fmt.Sprintf("disk.%d", idx))
|
||||
diskJson, err := jsonArray[idx].GetString() // data.GetString(fmt.Sprintf("disk.%d", idx))
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid disk description %s", err)
|
||||
}
|
||||
diskConfig, err := parseDiskInfo(ctx, userCred, diskJson)
|
||||
dataDiskDefs = append(dataDiskDefs, diskJson)
|
||||
}
|
||||
|
||||
for i := 0; i < len(dataDiskDefs); i += 1 {
|
||||
diskConfig, err := parseDiskInfo(ctx, userCred, jsonutils.NewString(dataDiskDefs[i]))
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("parse disk description error %s", err)
|
||||
}
|
||||
@@ -698,22 +783,43 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
if len(diskConfig.Driver) == 0 {
|
||||
diskConfig.Driver = osProf.DiskDriver
|
||||
}
|
||||
data.Add(jsonutils.Marshal(diskConfig), fmt.Sprintf("disk.%d", idx))
|
||||
data.Add(jsonutils.Marshal(diskConfig), fmt.Sprintf("disk.%d", i+1))
|
||||
}
|
||||
|
||||
resourceTypeStr := jsonutils.GetAnyString(data, []string{"resource_type"})
|
||||
durationStr := jsonutils.GetAnyString(data, []string{"duration"})
|
||||
|
||||
if len(durationStr) > 0 {
|
||||
|
||||
if !userCred.IsAdminAllow(consts.GetServiceType(), manager.KeywordPlural(), "renew") {
|
||||
return nil, httperrors.NewForbiddenError("only admin can create prepaid resource")
|
||||
}
|
||||
|
||||
if resourceTypeStr == HostResourceTypePrepaidRecycle {
|
||||
return nil, httperrors.NewConflictError("cannot create prepaid server on prepaid resource type")
|
||||
}
|
||||
|
||||
billingCycle, err := billing.ParseBillingCycle(durationStr)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid duration %s", durationStr)
|
||||
}
|
||||
|
||||
if !GetDriver(hypervisor).IsSupportedBillingCycle(billingCycle) {
|
||||
return nil, httperrors.NewInputParameterError("unsupported duration %s", durationStr)
|
||||
}
|
||||
|
||||
data.Add(jsonutils.NewString(BILLING_TYPE_PREPAID), "billing_type")
|
||||
data.Add(jsonutils.NewString(billingCycle.String()), "billing_cycle")
|
||||
// expired_at will be set later by callback
|
||||
// data.Add(jsonutils.NewTimeString(billingCycle.EndAt(time.Time{})), "expired_at")
|
||||
|
||||
data.Set("duration", jsonutils.NewString(billingCycle.String()))
|
||||
}
|
||||
}
|
||||
|
||||
data, err = ValidateScheduleCreateData(ctx, userCred, data, hypervisor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hypervisor, _ = data.GetString("hypervisor")
|
||||
|
||||
for idx := 0; data.Contains(fmt.Sprintf("net.%d", idx)); idx += 1 {
|
||||
netJson, err := data.Get(fmt.Sprintf("net.%d", idx))
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid network description %s", err)
|
||||
}
|
||||
netConfig, err := parseNetworkInfo(userCred, netJson)
|
||||
netJsonArray := jsonutils.GetArrayOfPrefix(data, "net")
|
||||
for idx := 0; idx < len(netJsonArray); idx += 1 { // .Contains(fmt.Sprintf("net.%d", idx)); idx += 1 {
|
||||
netConfig, err := parseNetworkInfo(userCred, netJsonArray[idx])
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("parse network description error %s", err)
|
||||
}
|
||||
@@ -724,18 +830,15 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
if len(netConfig.Driver) == 0 {
|
||||
netConfig.Driver = osProf.NetDriver
|
||||
}
|
||||
data.Add(jsonutils.Marshal(netConfig), fmt.Sprintf("net.%d", idx))
|
||||
data.Set(fmt.Sprintf("net.%d", idx), jsonutils.Marshal(netConfig))
|
||||
}
|
||||
|
||||
for idx := 0; data.Contains(fmt.Sprintf("isolated_device.%d", idx)); idx += 1 {
|
||||
isoDevArray := jsonutils.GetArrayOfPrefix(data, "isolated_device")
|
||||
for idx := 0; idx < len(isoDevArray); idx += 1 { // .Contains(fmt.Sprintf("isolated_device.%d", idx)); idx += 1 {
|
||||
if jsonutils.QueryBoolean(data, "backup", false) {
|
||||
return nil, httperrors.NewBadRequestError("Cannot create backup with isolated device")
|
||||
}
|
||||
devJson, err := data.Get(fmt.Sprintf("isolated_device.%d", idx))
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid isolated device description %s", err)
|
||||
}
|
||||
devConfig, err := IsolatedDeviceManager.parseDeviceInfo(userCred, devJson)
|
||||
devConfig, err := IsolatedDeviceManager.parseDeviceInfo(userCred, isoDevArray[idx])
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("parse isolated device description error %s", err)
|
||||
}
|
||||
@@ -743,7 +846,7 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.Add(jsonutils.Marshal(devConfig), fmt.Sprintf("isolated_device.%d", idx))
|
||||
data.Set(fmt.Sprintf("isolated_device.%d", idx), jsonutils.Marshal(devConfig))
|
||||
}
|
||||
|
||||
if data.Contains("cdrom") {
|
||||
@@ -800,35 +903,6 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// support sku here
|
||||
sku_id, _ := data.GetString("sku_id")
|
||||
if len(sku_id) > 0 {
|
||||
sku_id, vcpuCount, vmemSize, err := validateSkuData(sku_id)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(ServerSkuManager.Keyword(), sku_id)
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data.Add(jsonutils.NewString(sku_id), "sku_id")
|
||||
data.Add(jsonutils.NewInt(int64(vmemSize)), "vmem_size")
|
||||
data.Add(jsonutils.NewInt(int64(vcpuCount)), "vcpu_count")
|
||||
} else {
|
||||
vmemSize, vcpuCount, err := validateMemCpuData(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if vmemSize == 0 {
|
||||
return nil, httperrors.NewInputParameterError("Missing memory size")
|
||||
}
|
||||
if vcpuCount == 0 {
|
||||
vcpuCount = 1
|
||||
}
|
||||
data.Add(jsonutils.NewInt(int64(vmemSize)), "vmem_size")
|
||||
data.Add(jsonutils.NewInt(int64(vcpuCount)), "vcpu_count")
|
||||
}
|
||||
|
||||
if !jsonutils.QueryBoolean(data, "is_system", false) {
|
||||
err = manager.checkCreateQuota(ctx, userCred, ownerProjId, data,
|
||||
jsonutils.QueryBoolean(data, "backup", false))
|
||||
@@ -877,24 +951,25 @@ func getGuestResourceRequirements(ctx context.Context, userCred mcclient.TokenCr
|
||||
|
||||
diskSize := 0
|
||||
|
||||
for idx := 0; data.Contains(fmt.Sprintf("disk.%d", idx)); idx += 1 {
|
||||
dataJson, _ := data.Get(fmt.Sprintf("disk.%d", idx))
|
||||
diskConfig, _ := parseDiskInfo(ctx, userCred, dataJson)
|
||||
diskJsonArray := jsonutils.GetArrayOfPrefix(data, "disk")
|
||||
for idx := 0; idx < len(diskJsonArray); idx += 1 { // data.Contains(fmt.Sprintf("disk.%d", idx)); idx += 1 {
|
||||
diskConfig, _ := parseDiskInfo(ctx, userCred, diskJsonArray[idx])
|
||||
diskSize += diskConfig.SizeMb
|
||||
}
|
||||
|
||||
devCount := 0
|
||||
for idx := 0; data.Contains(fmt.Sprintf("isolated_device.%d", idx)); idx += 1 {
|
||||
devCount += 1
|
||||
}
|
||||
isoDevArray := jsonutils.GetArrayOfPrefix(data, "isolated_device")
|
||||
devCount := len(isoDevArray)
|
||||
// for idx := 0; data.Contains(fmt.Sprintf("isolated_device.%d", idx)); idx += 1 {
|
||||
// devCount += 1
|
||||
//}
|
||||
|
||||
eNicCnt := 0
|
||||
iNicCnt := 0
|
||||
eBw := 0
|
||||
iBw := 0
|
||||
for idx := 0; data.Contains(fmt.Sprintf("net.%d", idx)); idx += 1 {
|
||||
netJson, _ := data.Get(fmt.Sprintf("net.%d", idx))
|
||||
netConfig, _ := parseNetworkInfo(userCred, netJson)
|
||||
netJsonArray := jsonutils.GetArrayOfPrefix(data, "net")
|
||||
for idx := 0; idx < len(netJsonArray); idx += 1 { // .Contains(fmt.Sprintf("net.%d", idx)); idx += 1 {
|
||||
netConfig, _ := parseNetworkInfo(userCred, netJsonArray[idx])
|
||||
if isExitNetworkInfo(netConfig) {
|
||||
eNicCnt += 1
|
||||
eBw += netConfig.BwLimit
|
||||
@@ -1065,6 +1140,14 @@ func (self *SGuest) moreExtraInfo(extra *jsonutils.JSONDict) *jsonutils.JSONDict
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err := self.CanPerformPrepaidRecycle()
|
||||
if err != nil {
|
||||
extra.Add(jsonutils.JSONFalse, "can_recycle")
|
||||
} else {
|
||||
extra.Add(jsonutils.JSONTrue, "can_recycle")
|
||||
}
|
||||
|
||||
return extra
|
||||
}
|
||||
|
||||
@@ -1115,6 +1198,12 @@ func (self *SGuest) GetExtraDetails(ctx context.Context, userCred mcclient.Token
|
||||
}
|
||||
extra.Add(isGpu, "is_gpu")
|
||||
|
||||
if self.IsPrepaidRecycle() {
|
||||
extra.Add(jsonutils.JSONTrue, "is_prepaid_recycle")
|
||||
} else {
|
||||
extra.Add(jsonutils.JSONFalse, "is_prepaid_recycle")
|
||||
}
|
||||
|
||||
return self.moreExtraInfo(extra)
|
||||
}
|
||||
|
||||
@@ -1499,10 +1588,16 @@ func (self *SGuest) GetIsolatedDevices() []SIsolatedDevice {
|
||||
}
|
||||
|
||||
func (self *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, extVM cloudprovider.ICloudVM, projectId string, projectSync bool) error {
|
||||
recycle := false
|
||||
|
||||
if self.IsPrepaidRecycle() {
|
||||
recycle = true
|
||||
}
|
||||
|
||||
metaData := extVM.GetMetadata()
|
||||
diff, err := GuestManager.TableSpec().Update(self, func() error {
|
||||
extVM.Refresh()
|
||||
self.Name = extVM.GetName()
|
||||
// self.Name = extVM.GetName()
|
||||
self.Status = extVM.GetStatus()
|
||||
self.VcpuCount = extVM.GetVcpuCount()
|
||||
self.BootOrder = extVM.GetBootOrder()
|
||||
@@ -1511,25 +1606,24 @@ func (self *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.Token
|
||||
self.OsType = extVM.GetOSType()
|
||||
self.Bios = extVM.GetBios()
|
||||
self.Machine = extVM.GetMachine()
|
||||
self.HostId = host.Id
|
||||
self.ProjectId = userCred.GetProjectId()
|
||||
if !recycle {
|
||||
self.HostId = host.Id
|
||||
}
|
||||
|
||||
metaData := extVM.GetMetadata()
|
||||
instanceType := extVM.GetInstanceType()
|
||||
zoneExtId, err := metaData.GetString("zone_ext_id")
|
||||
if err != nil {
|
||||
log.Errorf("get zone external id fail %s", err)
|
||||
|
||||
if len(instanceType) > 0 {
|
||||
self.InstanceType = instanceType
|
||||
}
|
||||
|
||||
isku, err := ServerSkuManager.FetchByZoneExtId(zoneExtId, instanceType)
|
||||
if err != nil {
|
||||
log.Errorf("get sku fail %s", err)
|
||||
} else {
|
||||
self.SkuId = isku.GetId()
|
||||
}
|
||||
|
||||
if extVM.GetHypervisor() == HYPERVISOR_AWS && isku != nil {
|
||||
self.VmemSize = isku.(*SServerSku).MemorySizeMB
|
||||
if extVM.GetHypervisor() == HYPERVISOR_AWS {
|
||||
sku, err := ServerSkuManager.FetchSkuByNameAndHypervisor(instanceType, extVM.GetHypervisor(), false)
|
||||
if err == nil {
|
||||
self.VmemSize = sku.MemorySizeMB
|
||||
} else {
|
||||
self.VmemSize = extVM.GetVmemSizeMB()
|
||||
}
|
||||
} else {
|
||||
self.VmemSize = extVM.GetVmemSizeMB()
|
||||
}
|
||||
@@ -1542,8 +1636,10 @@ func (self *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.Token
|
||||
|
||||
self.IsEmulated = extVM.IsEmulated()
|
||||
|
||||
self.BillingType = extVM.GetBillingType()
|
||||
self.ExpiredAt = extVM.GetExpiredAt()
|
||||
if !recycle {
|
||||
self.BillingType = extVM.GetBillingType()
|
||||
self.ExpiredAt = extVM.GetExpiredAt()
|
||||
}
|
||||
|
||||
if metaData != nil && metaData.Contains("secgroupIds") {
|
||||
secgroupIds := []string{}
|
||||
@@ -1589,6 +1685,15 @@ func (self *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.Token
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if recycle {
|
||||
vhost := self.GetHost()
|
||||
err = vhost.syncWithCloudPrepaidVM(extVM, host, projectSync)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1618,7 +1723,8 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.
|
||||
|
||||
metaData := extVM.GetMetadata()
|
||||
instanceType := extVM.GetInstanceType()
|
||||
zoneExtId, err := metaData.GetString("zone_ext_id")
|
||||
|
||||
/*zoneExtId, err := metaData.GetString("zone_ext_id")
|
||||
if err != nil {
|
||||
log.Errorf("get zone external id fail %s", err)
|
||||
}
|
||||
@@ -1628,10 +1734,19 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.
|
||||
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
|
||||
}
|
||||
|
||||
if extVM.GetHypervisor() == HYPERVISOR_AWS && isku != nil {
|
||||
guest.VmemSize = isku.(*SServerSku).MemorySizeMB
|
||||
if extVM.GetHypervisor() == HYPERVISOR_AWS {
|
||||
sku, err := ServerSkuManager.FetchSkuByNameAndHypervisor(instanceType, extVM.GetHypervisor(), false)
|
||||
if err == nil {
|
||||
guest.VmemSize = sku.MemorySizeMB
|
||||
} else {
|
||||
guest.VmemSize = extVM.GetVmemSizeMB()
|
||||
}
|
||||
} else {
|
||||
guest.VmemSize = extVM.GetVmemSizeMB()
|
||||
}
|
||||
@@ -1661,9 +1776,10 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.
|
||||
}
|
||||
}
|
||||
|
||||
err = manager.TableSpec().Insert(&guest)
|
||||
err := manager.TableSpec().Insert(&guest)
|
||||
if err != nil {
|
||||
log.Errorf("Insert fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, secgroup := range extraSecgroups {
|
||||
@@ -1692,9 +1808,10 @@ func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.
|
||||
func (manager *SGuestManager) TotalCount(
|
||||
projectId string, rangeObj db.IStandaloneModel,
|
||||
status []string, hypervisors []string,
|
||||
includeSystem bool, pendingDelete bool, hostType string,
|
||||
includeSystem bool, pendingDelete bool,
|
||||
hostTypes []string, resourceTypes []string, providers []string,
|
||||
) SGuestCountStat {
|
||||
return totalGuestResourceCount(projectId, rangeObj, status, hypervisors, includeSystem, pendingDelete, hostType)
|
||||
return totalGuestResourceCount(projectId, rangeObj, status, hypervisors, includeSystem, pendingDelete, hostTypes, resourceTypes, providers)
|
||||
}
|
||||
|
||||
func (self *SGuest) detachNetwork(ctx context.Context, userCred mcclient.TokenCredential, network *SNetwork, reserve bool, deploy bool) error {
|
||||
@@ -2022,30 +2139,27 @@ func (self *SGuest) SyncVMDisks(ctx context.Context, userCred mcclient.TokenCred
|
||||
return result
|
||||
}
|
||||
|
||||
func filterGuestByRange(q *sqlchemy.SQuery, rangeObj db.IStandaloneModel, hostType string) *sqlchemy.SQuery {
|
||||
func filterGuestByRange(q *sqlchemy.SQuery, rangeObj db.IStandaloneModel, hostTypes []string, resourceTypes []string, providers []string) *sqlchemy.SQuery {
|
||||
hosts := HostManager.Query().SubQuery()
|
||||
q = q.Join(hosts, sqlchemy.AND(
|
||||
sqlchemy.Equals(hosts.Field("id"), q.Field("host_id")),
|
||||
sqlchemy.IsFalse(hosts.Field("deleted")),
|
||||
sqlchemy.IsTrue(hosts.Field("enabled")),
|
||||
sqlchemy.Equals(hosts.Field("host_status"), HOST_ONLINE)))
|
||||
hostTypes := []string{}
|
||||
if len(hostType) != 0 {
|
||||
hostTypes = append(hostTypes, hostType)
|
||||
}
|
||||
q = AttachUsageQuery(q, hosts, hosts.Field("id"), hostTypes, rangeObj)
|
||||
|
||||
q = q.Join(hosts, sqlchemy.Equals(hosts.Field("id"), q.Field("host_id")))
|
||||
q = q.Filter(sqlchemy.IsTrue(hosts.Field("enabled")))
|
||||
// q = q.Filter(sqlchemy.Equals(hosts.Field("host_status"), HOST_ONLINE))
|
||||
|
||||
q = AttachUsageQuery(q, hosts, hostTypes, resourceTypes, providers, rangeObj)
|
||||
return q
|
||||
}
|
||||
|
||||
type SGuestCountStat struct {
|
||||
TotalGuestCount int
|
||||
TotalCpuCount int
|
||||
TotalMemSize int
|
||||
TotalDiskSize int
|
||||
TotalIsolatedCount int
|
||||
TotalBackupCpuCount int
|
||||
TotalBackupMemSize int
|
||||
TotalBackupDiskSize int
|
||||
TotalGuestCount int
|
||||
TotalCpuCount int
|
||||
TotalMemSize int
|
||||
TotalDiskSize int
|
||||
TotalIsolatedCount int
|
||||
TotalBackupGuestCount int
|
||||
TotalBackupCpuCount int
|
||||
TotalBackupMemSize int
|
||||
TotalBackupDiskSize int
|
||||
}
|
||||
|
||||
func totalGuestResourceCount(
|
||||
@@ -2055,19 +2169,26 @@ func totalGuestResourceCount(
|
||||
hypervisors []string,
|
||||
includeSystem bool,
|
||||
pendingDelete bool,
|
||||
hostType string,
|
||||
hostTypes []string,
|
||||
resourceTypes []string,
|
||||
providers []string,
|
||||
) SGuestCountStat {
|
||||
|
||||
guestdisks := GuestdiskManager.Query().SubQuery()
|
||||
disks := DiskManager.Query().SubQuery()
|
||||
|
||||
diskQuery := guestdisks.Query(guestdisks.Field("guest_id"), sqlchemy.SUM("guest_disk_size", disks.Field("disk_size")))
|
||||
diskQuery = diskQuery.Join(disks, sqlchemy.AND(sqlchemy.Equals(guestdisks.Field("disk_id"), disks.Field("id")),
|
||||
sqlchemy.IsFalse(disks.Field("deleted"))))
|
||||
diskQuery = diskQuery.Join(disks, sqlchemy.Equals(guestdisks.Field("disk_id"), disks.Field("id")))
|
||||
diskQuery = diskQuery.GroupBy(guestdisks.Field("guest_id"))
|
||||
|
||||
diskSubQuery := diskQuery.SubQuery()
|
||||
diskBackupSubQuery := diskQuery.IsNotEmpty("backup_storage_id").SubQuery()
|
||||
|
||||
backupDiskQuery := guestdisks.Query(guestdisks.Field("guest_id"), sqlchemy.SUM("guest_disk_size", disks.Field("disk_size")))
|
||||
backupDiskQuery = backupDiskQuery.LeftJoin(disks, sqlchemy.Equals(guestdisks.Field("disk_id"), disks.Field("id")))
|
||||
backupDiskQuery = backupDiskQuery.Filter(sqlchemy.IsNotEmpty(disks.Field("backup_storage_id")))
|
||||
backupDiskQuery = backupDiskQuery.GroupBy(guestdisks.Field("guest_id"))
|
||||
|
||||
diskBackupSubQuery := backupDiskQuery.SubQuery()
|
||||
// diskBackupSubQuery := diskQuery.IsNotEmpty("backup_storage_id").SubQuery()
|
||||
|
||||
isolated := IsolatedDeviceManager.Query().SubQuery()
|
||||
|
||||
@@ -2078,7 +2199,11 @@ func totalGuestResourceCount(
|
||||
isoDevSubQuery := isoDevQuery.SubQuery()
|
||||
|
||||
guests := GuestManager.Query().SubQuery()
|
||||
guestBackupSubQuery := GuestManager.Query("id", "vcpu_count", "vmem_size").IsNotEmpty("backup_host_id").SubQuery()
|
||||
guestBackupSubQuery := GuestManager.Query(
|
||||
"id",
|
||||
"vcpu_count",
|
||||
"vmem_size",
|
||||
).IsNotEmpty("backup_host_id").SubQuery()
|
||||
|
||||
q := guests.Query(sqlchemy.COUNT("total_guest_count"),
|
||||
sqlchemy.SUM("total_cpu_count", guests.Field("vcpu_count")),
|
||||
@@ -2087,15 +2212,18 @@ func totalGuestResourceCount(
|
||||
sqlchemy.SUM("total_isolated_count", isoDevSubQuery.Field("device_sum")),
|
||||
sqlchemy.SUM("total_backup_disk_size", diskBackupSubQuery.Field("guest_disk_size")),
|
||||
sqlchemy.SUM("total_backup_cpu_count", guestBackupSubQuery.Field("vcpu_count")),
|
||||
sqlchemy.SUM("total_backup_mem_size", guestBackupSubQuery.Field("vmem_size")))
|
||||
sqlchemy.SUM("total_backup_mem_size", guestBackupSubQuery.Field("vmem_size")),
|
||||
sqlchemy.COUNT("total_backup_guest_count", guestBackupSubQuery.Field("id")),
|
||||
)
|
||||
|
||||
q = q.LeftJoin(guestBackupSubQuery, sqlchemy.Equals(guestBackupSubQuery.Field("id"), guests.Field("id")))
|
||||
|
||||
q = q.LeftJoin(diskSubQuery, sqlchemy.Equals(diskSubQuery.Field("guest_id"), guests.Field("id")))
|
||||
q = q.LeftJoin(guestBackupSubQuery, sqlchemy.Equals(guestBackupSubQuery.Field("id"), q.Field("id")))
|
||||
q = q.LeftJoin(diskBackupSubQuery, sqlchemy.Equals(diskBackupSubQuery.Field("guest_id"), guests.Field("id")))
|
||||
|
||||
q = q.LeftJoin(isoDevSubQuery, sqlchemy.Equals(isoDevSubQuery.Field("guest_id"), guests.Field("id")))
|
||||
|
||||
q = filterGuestByRange(q, rangeObj, hostType)
|
||||
q = filterGuestByRange(q, rangeObj, hostTypes, resourceTypes, providers)
|
||||
|
||||
if len(projectId) > 0 {
|
||||
q = q.Filter(sqlchemy.Equals(guests.Field("tenant_id"), projectId))
|
||||
@@ -2135,13 +2263,24 @@ func (self *SGuest) getDefaultNetworkConfig() *SNetworkConfig {
|
||||
}
|
||||
|
||||
func (self *SGuest) CreateNetworksOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, data *jsonutils.JSONDict, pendingUsage quotas.IQuota) error {
|
||||
idx := 0
|
||||
netJsonArray := jsonutils.GetArrayOfPrefix(data, "net")
|
||||
/* idx := 0
|
||||
for idx = 0; data.Contains(fmt.Sprintf("net.%d", idx)); idx += 1 {
|
||||
netJson, err := data.Get(fmt.Sprintf("net.%d", idx))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
netConfig, err := parseNetworkInfo(userCred, netJson)
|
||||
if netJson == jsonutils.JSONNull {
|
||||
break
|
||||
}
|
||||
|
||||
}*/
|
||||
if len(netJsonArray) == 0 {
|
||||
netConfig := self.getDefaultNetworkConfig()
|
||||
return self.attach2RandomNetwork(ctx, userCred, host, netConfig, pendingUsage)
|
||||
}
|
||||
for idx := 0; idx < len(netJsonArray); idx += 1 {
|
||||
netConfig, err := parseNetworkInfo(userCred, netJsonArray[idx])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -2150,10 +2289,6 @@ func (self *SGuest) CreateNetworksOnHost(ctx context.Context, userCred mcclient.
|
||||
return err
|
||||
}
|
||||
}
|
||||
if idx == 0 {
|
||||
netConfig := self.getDefaultNetworkConfig()
|
||||
return self.attach2RandomNetwork(ctx, userCred, host, netConfig, pendingUsage)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2196,17 +2331,15 @@ func (self *SGuest) attach2RandomNetwork(ctx context.Context, userCred mcclient.
|
||||
return driver.Attach2RandomNetwork(self, ctx, userCred, host, netConfig, pendingUsage)
|
||||
}
|
||||
|
||||
func (self *SGuest) CreateDisksOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, data *jsonutils.JSONDict, pendingUsage quotas.IQuota) error {
|
||||
for idx := 0; data.Contains(fmt.Sprintf("disk.%d", idx)); idx += 1 {
|
||||
diskJson, err := data.Get(fmt.Sprintf("disk.%d", idx))
|
||||
func (self *SGuest) CreateDisksOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost,
|
||||
data *jsonutils.JSONDict, pendingUsage quotas.IQuota, inheritBilling bool) error {
|
||||
diskJsonArray := jsonutils.GetArrayOfPrefix(data, "disk")
|
||||
for idx := 0; idx < len(diskJsonArray); idx += 1 { // .Contains(fmt.Sprintf("disk.%d", idx)); idx += 1 {
|
||||
diskConfig, err := parseDiskInfo(ctx, userCred, diskJsonArray[idx])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
diskConfig, err := parseDiskInfo(ctx, userCred, diskJson)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
disk, err := self.createDiskOnHost(ctx, userCred, host, diskConfig, pendingUsage)
|
||||
disk, err := self.createDiskOnHost(ctx, userCred, host, diskConfig, pendingUsage, inheritBilling)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -2215,7 +2348,8 @@ func (self *SGuest) CreateDisksOnHost(ctx context.Context, userCred mcclient.Tok
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) createDiskOnStorage(ctx context.Context, userCred mcclient.TokenCredential, storage *SStorage, diskConfig *SDiskConfig, pendingUsage quotas.IQuota) (*SDisk, error) {
|
||||
func (self *SGuest) createDiskOnStorage(ctx context.Context, userCred mcclient.TokenCredential, storage *SStorage,
|
||||
diskConfig *SDiskConfig, pendingUsage quotas.IQuota, inheritBilling bool) (*SDisk, error) {
|
||||
lockman.LockObject(ctx, storage)
|
||||
defer lockman.ReleaseObject(ctx, storage)
|
||||
|
||||
@@ -2223,7 +2357,20 @@ func (self *SGuest) createDiskOnStorage(ctx context.Context, userCred mcclient.T
|
||||
defer lockman.ReleaseClass(ctx, QuotaManager, self.ProjectId)
|
||||
|
||||
diskName := fmt.Sprintf("vdisk_%s_%d", self.Name, time.Now().UnixNano())
|
||||
disk, err := storage.createDisk(diskName, diskConfig, userCred, self.ProjectId, true, self.IsSystem)
|
||||
|
||||
billingType := BILLING_TYPE_POSTPAID
|
||||
billingCycle := ""
|
||||
if inheritBilling {
|
||||
billingType = self.BillingType
|
||||
billingCycle = self.BillingCycle
|
||||
}
|
||||
|
||||
autoDelete := false
|
||||
if storage.IsLocal() || billingType == BILLING_TYPE_PREPAID {
|
||||
autoDelete = true
|
||||
}
|
||||
disk, err := storage.createDisk(diskName, diskConfig, userCred, self.ProjectId, autoDelete, self.IsSystem,
|
||||
billingType, billingCycle)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -2236,12 +2383,13 @@ func (self *SGuest) createDiskOnStorage(ctx context.Context, userCred mcclient.T
|
||||
return disk, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) createDiskOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, diskConfig *SDiskConfig, pendingUsage quotas.IQuota) (*SDisk, error) {
|
||||
func (self *SGuest) createDiskOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost,
|
||||
diskConfig *SDiskConfig, pendingUsage quotas.IQuota, inheritBilling bool) (*SDisk, error) {
|
||||
storage := self.GetDriver().ChooseHostStorage(host, diskConfig.Backend)
|
||||
if storage == nil {
|
||||
return nil, fmt.Errorf("No storage to create disk")
|
||||
}
|
||||
disk, err := self.createDiskOnStorage(ctx, userCred, storage, diskConfig, pendingUsage)
|
||||
disk, err := self.createDiskOnStorage(ctx, userCred, storage, diskConfig, pendingUsage, inheritBilling)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2262,12 +2410,9 @@ func (self *SGuest) createDiskOnHost(ctx context.Context, userCred mcclient.Toke
|
||||
}
|
||||
|
||||
func (self *SGuest) CreateIsolatedDeviceOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, data *jsonutils.JSONDict, pendingUsage quotas.IQuota) error {
|
||||
for idx := 0; data.Contains(fmt.Sprintf("isolated_device.%d", idx)); idx += 1 {
|
||||
devJson, err := data.Get(fmt.Sprintf("isolated_device.%d", idx))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
devConfig, err := IsolatedDeviceManager.parseDeviceInfo(userCred, devJson)
|
||||
devJsonArray := jsonutils.GetArrayOfPrefix(data, "isolated_device")
|
||||
for idx := 0; idx < len(devJsonArray); idx += 1 { // .Contains(fmt.Sprintf("isolated_device.%d", idx)); idx += 1 {
|
||||
devConfig, err := IsolatedDeviceManager.parseDeviceInfo(userCred, devJsonArray[idx])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -3033,7 +3178,7 @@ func (self *SGuest) GetShortDesc() *jsonutils.JSONDict {
|
||||
billingInfo.PriceKey = priceKey
|
||||
}
|
||||
|
||||
billingInfo.ChargeType = self.GetChargeType()
|
||||
self.FetchCloudBillingInfo(&billingInfo)
|
||||
|
||||
desc.Update(jsonutils.Marshal(billingInfo))
|
||||
|
||||
@@ -3119,10 +3264,8 @@ func (manager *SGuestManager) GetIpInProjectWithName(projectId, name string, isE
|
||||
sqlchemy.AND(
|
||||
sqlchemy.Equals(guests.Field("id"), guestnics.Field("guest_id")),
|
||||
sqlchemy.OR(sqlchemy.IsNull(guests.Field("pending_deleted")),
|
||||
sqlchemy.IsFalse(guests.Field("pending_deleted"))),
|
||||
sqlchemy.IsFalse(guests.Field("deleted")))).
|
||||
Join(networks, sqlchemy.AND(sqlchemy.Equals(networks.Field("id"), guestnics.Field("network_id")),
|
||||
sqlchemy.IsFalse(networks.Field("deleted")))).
|
||||
sqlchemy.IsFalse(guests.Field("pending_deleted"))))).
|
||||
Join(networks, sqlchemy.Equals(networks.Field("id"), guestnics.Field("network_id"))).
|
||||
Filter(sqlchemy.Equals(guests.Field("name"), name)).
|
||||
Filter(sqlchemy.NotEquals(guestnics.Field("ip_addr"), "")).
|
||||
Filter(sqlchemy.IsNotNull(guestnics.Field("ip_addr"))).
|
||||
@@ -3168,7 +3311,7 @@ func (manager *SGuestManager) getExpiredPendingDeleteGuests() []SGuest {
|
||||
deadline := time.Now().Add(time.Duration(options.Options.PendingDeleteExpireSeconds*-1) * time.Second)
|
||||
|
||||
q := manager.Query()
|
||||
q = q.IsTrue("pending_deleted").LT("pending_deleted_at", deadline).In("hypervisor", []string{"aliyun"}).Limit(options.Options.PendingDeleteMaxCleanBatchSize)
|
||||
q = q.IsTrue("pending_deleted").LT("pending_deleted_at", deadline).Limit(options.Options.PendingDeleteMaxCleanBatchSize)
|
||||
|
||||
guests := make([]SGuest, 0)
|
||||
err := db.FetchModelObjects(GuestManager, q, &guests)
|
||||
@@ -3180,7 +3323,7 @@ func (manager *SGuestManager) getExpiredPendingDeleteGuests() []SGuest {
|
||||
return guests
|
||||
}
|
||||
|
||||
func (manager *SGuestManager) CleanPendingDeleteServers(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
func (manager *SGuestManager) CleanPendingDeleteServers(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
guests := manager.getExpiredPendingDeleteGuests()
|
||||
if guests == nil {
|
||||
return
|
||||
@@ -3190,6 +3333,32 @@ func (manager *SGuestManager) CleanPendingDeleteServers(ctx context.Context, use
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *SGuestManager) getExpiredPrepaidGuests() []SGuest {
|
||||
deadline := time.Now().Add(time.Duration(options.Options.PrepaidExpireCheckSeconds*-1) * time.Second)
|
||||
|
||||
q := manager.Query()
|
||||
q = q.Equals("billing_type", BILLING_TYPE_PREPAID).LT("expired_at", deadline).Limit(options.Options.ExpiredPrepaidMaxCleanBatchSize)
|
||||
|
||||
guests := make([]SGuest, 0)
|
||||
err := db.FetchModelObjects(GuestManager, q, &guests)
|
||||
if err != nil {
|
||||
log.Errorf("fetch guests error %s", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
return guests
|
||||
}
|
||||
|
||||
func (manager *SGuestManager) DeleteExpiredPrepaidServers(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
guests := manager.getExpiredPrepaidGuests()
|
||||
if guests == nil {
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(guests); i += 1 {
|
||||
guests[i].StartDeleteGuestTask(ctx, userCred, "", false, true)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuest) GetEip() (*SElasticip, error) {
|
||||
return ElasticipManager.getEipForInstance("server", self.Id)
|
||||
}
|
||||
@@ -3446,3 +3615,16 @@ func (self *SGuest) GuestDisksHasSnapshot() bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SGuest) OnScheduleToHost(ctx context.Context, userCred mcclient.TokenCredential, hostId string) error {
|
||||
err := self.SetHostId(hostId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
notes := jsonutils.NewDict()
|
||||
notes.Add(jsonutils.NewString(hostId), "host_id")
|
||||
db.OpsLog.LogEvent(self, db.ACT_SCHEDULE, notes, userCred)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -67,7 +67,12 @@ func (manager *SGuestsecgroupManager) newGuestSecgroup(ctx context.Context, user
|
||||
func (manager *SGuestsecgroupManager) DeleteGuestSecgroup(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, secgroup *SSecurityGroup) error {
|
||||
gss := []SGuestsecgroup{}
|
||||
q := manager.Query()
|
||||
q = q.Equals("guest_id", guest.Id).Equals("secgroup_id", secgroup.Id)
|
||||
if guest != nil {
|
||||
q = q.Equals("guest_id", guest.Id)
|
||||
}
|
||||
if secgroup != nil {
|
||||
q = q.Equals("secgroup_id", secgroup.Id)
|
||||
}
|
||||
if err := db.FetchModelObjects(manager, q, &gss); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -93,8 +92,9 @@ func ValidateScheduleCreateData(ctx context.Context, userCred mcclient.TokenCred
|
||||
return nil, httperrors.NewInputParameterError("invalid aggregate_strategy")
|
||||
}
|
||||
}
|
||||
for idx := 0; data.Contains(fmt.Sprintf("schedtag.%d", idx)); idx += 1 {
|
||||
aggStr, _ := data.GetString(fmt.Sprintf("schedtag.%d", idx))
|
||||
aggArray := jsonutils.GetArrayOfPrefix(data, "schedtag")
|
||||
for idx := 0; idx < len(aggArray); idx += 1 { // data.Contains(fmt.Sprintf("schedtag.%d", idx)); idx += 1 {
|
||||
aggStr, _ := aggArray[idx].GetString() // .GetString(fmt.Sprintf("schedtag.%d", idx))
|
||||
if len(aggStr) > 0 {
|
||||
parts := strings.Split(aggStr, ":")
|
||||
if len(parts) >= 2 && len(parts[0]) > 0 && len(parts[1]) > 0 {
|
||||
|
||||
@@ -0,0 +1,645 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang-plus/errors"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
func (self *SHost) GetResourceType() string {
|
||||
if len(self.ResourceType) > 0 {
|
||||
return self.ResourceType
|
||||
}
|
||||
return HostResourceTypeDefault
|
||||
}
|
||||
|
||||
func (self *SGuest) AllowPerformPrepaidRecycle(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowPerform(userCred, self, "prepaid-recycle")
|
||||
}
|
||||
|
||||
func (self *SGuest) CanPerformPrepaidRecycle() error {
|
||||
if self.BillingType != BILLING_TYPE_PREPAID {
|
||||
return fmt.Errorf("recycle prepaid server only")
|
||||
}
|
||||
if self.ExpiredAt.Before(time.Now()) {
|
||||
return fmt.Errorf("prepaid expired")
|
||||
}
|
||||
host := self.GetHost()
|
||||
if host == nil {
|
||||
return fmt.Errorf("no host")
|
||||
}
|
||||
if !host.IsManaged() {
|
||||
return fmt.Errorf("only managed prepaid server can be pooled")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformPrepaidRecycle(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
err := self.CanPerformPrepaidRecycle()
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInvalidStatusError(err.Error())
|
||||
}
|
||||
|
||||
err = self.doPrepaidRecycle(ctx, userCred)
|
||||
if err != nil {
|
||||
logclient.AddActionLog(self, logclient.ACT_RECYCLE_PREPAID, self.GetShortDesc(), userCred, false)
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
|
||||
db.OpsLog.LogEvent(self, db.ACT_RECYCLE_PREPAID, self.GetShortDesc(), userCred)
|
||||
logclient.AddActionLog(self, logclient.ACT_RECYCLE_PREPAID, self.GetShortDesc(), userCred, true)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) doPrepaidRecycle(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
lockman.LockClass(ctx, HostManager, userCred.GetProjectId())
|
||||
defer lockman.ReleaseClass(ctx, HostManager, userCred.GetProjectId())
|
||||
|
||||
return self.doPrepaidRecycleNoLock(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SGuest) doPrepaidRecycleNoLock(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
oHost := self.GetHost()
|
||||
|
||||
fakeHost := SHost{}
|
||||
fakeHost.SetModelManager(HostManager)
|
||||
|
||||
fakeHost.Name = fmt.Sprintf("%s-host", self.Name)
|
||||
fakeHost.CpuCount = self.VcpuCount
|
||||
fakeHost.NodeCount = 1
|
||||
fakeHost.CpuCmtbound = 1.0
|
||||
|
||||
fakeHost.MemCmtbound = 1.0
|
||||
fakeHost.MemReserved = 0
|
||||
fakeHost.MemSize = self.VmemSize
|
||||
|
||||
guestdisks := self.GetDisks()
|
||||
|
||||
storageInfo := make([]baremetal.BaremetalStorage, 0)
|
||||
totalSize := 0
|
||||
for i := 0; i < len(guestdisks); i += 1 {
|
||||
disk := guestdisks[i].GetDisk()
|
||||
storage := disk.GetStorage()
|
||||
|
||||
totalSize += disk.DiskSize
|
||||
|
||||
if len(fakeHost.StorageType) == 0 {
|
||||
fakeHost.StorageType = storage.StorageType
|
||||
}
|
||||
|
||||
info := baremetal.BaremetalStorage{}
|
||||
info.Size = int64(disk.DiskSize)
|
||||
info.Index = int64(i)
|
||||
info.Slot = i
|
||||
info.Driver = storage.StorageType
|
||||
info.Rotate = (storage.MediumType != DISK_TYPE_SSD)
|
||||
|
||||
storageInfo = append(storageInfo, info)
|
||||
}
|
||||
|
||||
fakeHost.StorageDriver = baremetal.DISK_DRIVER_LINUX
|
||||
fakeHost.StorageSize = totalSize
|
||||
fakeHost.StorageInfo = jsonutils.Marshal(&storageInfo)
|
||||
|
||||
fakeHost.ZoneId = self.getZone().GetId()
|
||||
fakeHost.IsBaremetal = false
|
||||
fakeHost.IsMaintenance = false
|
||||
fakeHost.ResourceType = HostResourceTypePrepaidRecycle
|
||||
|
||||
guestnics := self.GetNetworks()
|
||||
if len(guestnics) == 0 {
|
||||
msg := "no network info on guest????"
|
||||
log.Errorf(msg)
|
||||
return fmt.Errorf(msg)
|
||||
}
|
||||
fakeHost.AccessIp = guestnics[0].IpAddr
|
||||
fakeHost.AccessMac = guestnics[0].MacAddr
|
||||
|
||||
fakeHost.BillingType = BILLING_TYPE_PREPAID
|
||||
fakeHost.BillingCycle = self.BillingCycle
|
||||
fakeHost.ExpiredAt = self.ExpiredAt
|
||||
|
||||
fakeHost.Status = HOST_STATUS_RUNNING
|
||||
fakeHost.HostStatus = HOST_ONLINE
|
||||
fakeHost.Enabled = true
|
||||
fakeHost.HostType = oHost.HostType
|
||||
fakeHost.ExternalId = oHost.ExternalId
|
||||
fakeHost.RealExternalId = self.ExternalId
|
||||
fakeHost.ManagerId = oHost.ManagerId
|
||||
fakeHost.IsEmulated = true
|
||||
fakeHost.Description = "fake host for prepaid vm recycling"
|
||||
|
||||
err := HostManager.TableSpec().Insert(&fakeHost)
|
||||
if err != nil {
|
||||
log.Errorf("fail to insert fake host %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < len(guestnics); i += 1 {
|
||||
var nicType string
|
||||
if i == 0 {
|
||||
nicType = NIC_TYPE_ADMIN
|
||||
}
|
||||
err = fakeHost.addNetif(ctx, userCred,
|
||||
guestnics[i].MacAddr,
|
||||
guestnics[i].GetNetwork().WireId,
|
||||
"",
|
||||
1000,
|
||||
nicType,
|
||||
int8(i),
|
||||
tristate.True,
|
||||
1500,
|
||||
false,
|
||||
fmt.Sprintf("eth%d", i),
|
||||
fmt.Sprintf("br%d", i),
|
||||
false,
|
||||
false)
|
||||
if err != nil {
|
||||
log.Errorf("fail to addNetInterface %d: %s", i, err)
|
||||
fakeHost.RealDelete(ctx, userCred)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
storageSize := 0
|
||||
var externalId string
|
||||
for i := 0; i < len(guestdisks); i += 1 {
|
||||
disk := guestdisks[i].GetDisk()
|
||||
storage := disk.GetStorage()
|
||||
if disk.BillingType == BILLING_TYPE_PREPAID {
|
||||
storageSize += disk.DiskSize
|
||||
if len(externalId) == 0 {
|
||||
externalId = storage.ExternalId
|
||||
} else {
|
||||
if externalId != storage.ExternalId {
|
||||
msg := "inconsistent storage !!!!"
|
||||
log.Errorf(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sysStorage := guestdisks[0].GetDisk().GetStorage()
|
||||
|
||||
fakeStorage := SStorage{}
|
||||
fakeStorage.SetModelManager(StorageManager)
|
||||
|
||||
fakeStorage.Name = fmt.Sprintf("%s-storage", self.Name)
|
||||
fakeStorage.Capacity = storageSize
|
||||
fakeStorage.StorageType = STORAGE_LOCAL
|
||||
fakeStorage.MediumType = sysStorage.MediumType
|
||||
fakeStorage.Cmtbound = 1.0
|
||||
fakeStorage.ZoneId = fakeHost.ZoneId
|
||||
fakeStorage.StoragecacheId = sysStorage.StoragecacheId
|
||||
fakeStorage.Enabled = true
|
||||
fakeStorage.Status = STORAGE_ONLINE
|
||||
fakeStorage.Description = "fake storage for prepaid vm recycling"
|
||||
fakeStorage.IsEmulated = true
|
||||
fakeStorage.ManagerId = sysStorage.ManagerId
|
||||
fakeStorage.ExternalId = externalId
|
||||
|
||||
err = StorageManager.TableSpec().Insert(&fakeStorage)
|
||||
if err != nil {
|
||||
log.Errorf("fail to insert fake storage %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = fakeHost.Attach2Storage(ctx, userCred, &fakeStorage, "")
|
||||
if err != nil {
|
||||
log.Errorf("fail to add fake storage: %s", err)
|
||||
fakeHost.RealDelete(ctx, userCred)
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = self.GetModelManager().TableSpec().Update(self, func() error {
|
||||
// clear billing information
|
||||
self.BillingType = BILLING_TYPE_POSTPAID
|
||||
self.BillingCycle = ""
|
||||
self.ExpiredAt = time.Time{}
|
||||
// switch to fakeHost
|
||||
self.HostId = fakeHost.Id
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("clear billing information fail: %s", err)
|
||||
fakeHost.RealDelete(ctx, userCred)
|
||||
return err
|
||||
}
|
||||
|
||||
for i := 0; i < len(guestdisks); i += 1 {
|
||||
disk := guestdisks[i].GetDisk()
|
||||
|
||||
if disk.BillingType == BILLING_TYPE_PREPAID {
|
||||
_, err = disk.GetModelManager().TableSpec().Update(disk, func() error {
|
||||
disk.BillingType = BILLING_TYPE_POSTPAID
|
||||
disk.BillingCycle = ""
|
||||
disk.ExpiredAt = time.Time{}
|
||||
disk.StorageId = fakeStorage.Id
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("clear billing information for %d %s disk fail: %s", i, disk.DiskType, err)
|
||||
fakeHost.RealDelete(ctx, userCred)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) AllowPerformUndoPrepaidRecycle(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowPerform(userCred, self, "undo-prepaid-recycle")
|
||||
}
|
||||
|
||||
func (self *SGuest) PerformUndoPrepaidRecycle(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
host := self.GetHost()
|
||||
|
||||
if host == nil {
|
||||
return nil, httperrors.NewInvalidStatusError("no valid host")
|
||||
}
|
||||
|
||||
if host.Enabled {
|
||||
return nil, httperrors.NewInvalidStatusError("host should be disabled")
|
||||
}
|
||||
|
||||
if host.ResourceType != HostResourceTypePrepaidRecycle || host.BillingType != BILLING_TYPE_PREPAID {
|
||||
return nil, httperrors.NewInvalidStatusError("host is not a prepaid recycle host")
|
||||
}
|
||||
|
||||
err := doUndoPrepaidRecycle(ctx, userCred, host, self)
|
||||
if err != nil {
|
||||
logclient.AddActionLog(self, logclient.ACT_UNDO_RECYCLE_PREPAID, self.GetShortDesc(), userCred, false)
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
|
||||
db.OpsLog.LogEvent(self, db.ACT_UNDO_RECYCLE_PREPAID, self.GetShortDesc(), userCred)
|
||||
logclient.AddActionLog(self, logclient.ACT_UNDO_RECYCLE_PREPAID, self.GetShortDesc(), userCred, true)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SHost) AllowPerformUndoPrepaidRecycle(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowPerform(userCred, self, "undo-prepaid-recycle")
|
||||
}
|
||||
|
||||
func (self *SHost) PerformUndoPrepaidRecycle(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
if self.Enabled {
|
||||
return nil, httperrors.NewInvalidStatusError("host should be disabled")
|
||||
}
|
||||
|
||||
if self.ResourceType != HostResourceTypePrepaidRecycle || self.BillingType != BILLING_TYPE_PREPAID {
|
||||
return nil, httperrors.NewInvalidStatusError("host is not a prepaid recycle host")
|
||||
}
|
||||
|
||||
guests := self.GetGuests()
|
||||
|
||||
if len(guests) == 0 {
|
||||
return nil, httperrors.NewInvalidStatusError("cannot delete a recycle host without active instance")
|
||||
}
|
||||
|
||||
if len(guests) > 1 {
|
||||
return nil, httperrors.NewInvalidStatusError("a recycle host shoud not allocate more than 1 guest")
|
||||
}
|
||||
|
||||
err := doUndoPrepaidRecycle(ctx, userCred, self, &guests[0])
|
||||
if err != nil {
|
||||
logclient.AddActionLog(self, logclient.ACT_UNDO_RECYCLE_PREPAID, self.GetShortDesc(), userCred, false)
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
|
||||
db.OpsLog.LogEvent(self, db.ACT_UNDO_RECYCLE_PREPAID, self.GetShortDesc(), userCred)
|
||||
logclient.AddActionLog(self, logclient.ACT_UNDO_RECYCLE_PREPAID, self.GetShortDesc(), userCred, true)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func findIdiskById(idisks []cloudprovider.ICloudDisk, uuid string) cloudprovider.ICloudDisk {
|
||||
for i := 0; i < len(idisks); i += 1 {
|
||||
if idisks[i].GetGlobalId() == uuid {
|
||||
return idisks[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func doUndoPrepaidRecycle(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, server *SGuest) error {
|
||||
if host.RealExternalId != server.ExternalId {
|
||||
msg := "host and server external id not match!!!!"
|
||||
log.Errorf(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
q := HostManager.Query()
|
||||
q = q.Equals("external_id", host.ExternalId)
|
||||
q = q.Equals("host_type", host.HostType)
|
||||
q = q.IsNullOrEmpty("resource_type")
|
||||
|
||||
oHostCnt := q.Count()
|
||||
|
||||
if oHostCnt == 0 {
|
||||
msg := "orthordox host not found???"
|
||||
log.Errorf(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
if oHostCnt > 1 {
|
||||
msg := fmt.Sprintf("more than 1 (%d) orthordox host found???", oHostCnt)
|
||||
log.Errorf(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
oHost := SHost{}
|
||||
oHost.SetModelManager(HostManager)
|
||||
|
||||
err := q.First(&oHost)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to query orthordox host %s", err)
|
||||
log.Errorf(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
iHost, err := oHost.GetIHost()
|
||||
if err != nil {
|
||||
msg := fmt.Sprint("fail to find ihost %s", err)
|
||||
log.Errorf(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
iVM, err := iHost.GetIVMById(server.ExternalId)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("fail to GetIVMById %s", err)
|
||||
log.Errorf(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
idisks, err := iVM.GetIDisks()
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("iVM.GetIDisks fail %s", err)
|
||||
log.Errorf(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
_, err = server.GetModelManager().TableSpec().Update(server, func() error {
|
||||
// recover billing information
|
||||
server.BillingType = BILLING_TYPE_PREPAID
|
||||
server.BillingCycle = host.BillingCycle
|
||||
server.ExpiredAt = host.ExpiredAt
|
||||
// switch to original Host
|
||||
server.HostId = oHost.Id
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("fail to recover vm hostId %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
guestdisks := server.GetDisks()
|
||||
|
||||
for i := 0; i < len(guestdisks); i += 1 {
|
||||
disk := guestdisks[i].GetDisk()
|
||||
storage := disk.GetStorage()
|
||||
idisk := findIdiskById(idisks, disk.ExternalId)
|
||||
if idisk == nil {
|
||||
msg := fmt.Sprintf("fail to find idisk by ID %s: %s", disk.ExternalId, err)
|
||||
log.Errorf(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
istorage, err := idisk.GetIStorage()
|
||||
if err != nil {
|
||||
log.Errorf("idisk.GetIStorage fail %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
oStorageObj, err := StorageManager.FetchByExternalId(istorage.GetGlobalId())
|
||||
if err != nil {
|
||||
log.Errorf("StorageManager.FetchByExternalId fail %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
oStorage := oStorageObj.(*SStorage)
|
||||
|
||||
if storage.StorageType == STORAGE_LOCAL {
|
||||
_, err = disk.GetModelManager().TableSpec().Update(disk, func() error {
|
||||
disk.BillingType = BILLING_TYPE_PREPAID
|
||||
disk.BillingCycle = host.BillingCycle
|
||||
disk.ExpiredAt = host.ExpiredAt
|
||||
disk.StorageId = oStorage.Id
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("fail to recover prepaid disk info %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = host.RealDelete(ctx, userCred)
|
||||
if err != nil {
|
||||
log.Errorf("fail to delete fake host")
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) IsPrepaidRecycle() bool {
|
||||
host := self.GetHost()
|
||||
if host == nil {
|
||||
return false
|
||||
}
|
||||
return host.IsPrepaidRecycle()
|
||||
}
|
||||
|
||||
func (host *SHost) IsPrepaidRecycle() bool {
|
||||
if host.ResourceType != HostResourceTypePrepaidRecycle {
|
||||
return false
|
||||
}
|
||||
if host.BillingType != BILLING_TYPE_PREPAID {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SHost) BorrowIpAddrsFromGuest(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest) error {
|
||||
guestnics := guest.GetNetworks()
|
||||
for i := 0; i < len(guestnics); i += 1 {
|
||||
err := guestnics[i].Detach(ctx, userCred)
|
||||
if err != nil {
|
||||
log.Errorf("fail to detach guest network %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
netif := self.GetNetInterface(guestnics[i].MacAddr)
|
||||
if netif == nil {
|
||||
msg := fmt.Sprintf("fail to find netinterface for mac %s", guestnics[i].MacAddr)
|
||||
log.Errorf(msg)
|
||||
return fmt.Errorf(msg)
|
||||
}
|
||||
|
||||
err = self.EnableNetif(ctx, userCred, netif, "", guestnics[i].IpAddr, "", false, false)
|
||||
if err != nil {
|
||||
log.Errorf("fail to enable netif %s %s", guestnics[i].IpAddr, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (host *SHost) SetGuestCreateNetworkAndDiskParams(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
ihost, err := host.GetIHost()
|
||||
if err != nil {
|
||||
log.Errorf("host.GetIHost fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ivm, err := ihost.GetIVMById(host.RealExternalId)
|
||||
if err != nil {
|
||||
log.Errorf("ihost.GetIVMById(host.RealExternalId) fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
idisks, err := ivm.GetIDisks()
|
||||
if err != nil {
|
||||
log.Errorf("ivm.GetIDisks fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
netifs := host.GetNetInterfaces()
|
||||
netIdx := 0
|
||||
for i := 0; i < len(netifs); i += 1 {
|
||||
hn := netifs[i].GetBaremetalNetwork()
|
||||
if hn != nil {
|
||||
err := host.DisableNetif(ctx, userCred, &netifs[i], true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packedMac := strings.Replace(netifs[i].Mac, ":", "", -1)
|
||||
netDesc := fmt.Sprintf("%s:%s:%s:[reserved]", packedMac, hn.IpAddr, hn.NetworkId)
|
||||
params.Set(fmt.Sprintf("net.%d", netIdx), jsonutils.NewString(netDesc))
|
||||
netIdx += 1
|
||||
}
|
||||
}
|
||||
params.Set(fmt.Sprintf("net.%d", netIdx), jsonutils.JSONNull)
|
||||
|
||||
for i := 0; i < len(idisks); i += 1 {
|
||||
/*istorage, err := idisks[i].GetIStorage()
|
||||
if err != nil {
|
||||
log.Errorf("idisks[i].GetIStorage fail %s", err)
|
||||
return nil, err
|
||||
}*/
|
||||
|
||||
key := fmt.Sprintf("disk.%d", i)
|
||||
jsonConf, _ := params.Get(key)
|
||||
if jsonConf != nil && jsonConf != jsonutils.JSONNull {
|
||||
conf, err := parseDiskInfo(ctx, userCred, jsonConf)
|
||||
if err != nil {
|
||||
log.Debugf("parseDiskInfo %s fail %s", jsonConf, err)
|
||||
return nil, err
|
||||
}
|
||||
conf.SizeMb = idisks[i].GetDiskSizeMB()
|
||||
conf.Backend = STORAGE_LOCAL
|
||||
params.Set(key, jsonutils.Marshal(conf))
|
||||
} else {
|
||||
strConf := fmt.Sprintf("%s:%d", STORAGE_LOCAL, idisks[i].GetDiskSizeMB())
|
||||
conf, err := parseDiskInfo(ctx, userCred, jsonutils.NewString(strConf))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Set(key, jsonutils.Marshal(conf))
|
||||
}
|
||||
}
|
||||
params.Set(fmt.Sprintf("disk.%d", len(idisks)), jsonutils.JSONNull)
|
||||
|
||||
// log.Debugf("params after rebuid: %s", params.String())
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (host *SHost) RebuildRecycledGuest(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest) error {
|
||||
oHost := SHost{}
|
||||
oHost.SetModelManager(HostManager)
|
||||
|
||||
q := HostManager.Query()
|
||||
q = q.Equals("external_id", host.ExternalId)
|
||||
q = q.IsNullOrEmpty("resource_type")
|
||||
err := q.First(&oHost)
|
||||
if err != nil {
|
||||
log.Errorf("query oHost fail %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = guest.SetExternalId(host.RealExternalId)
|
||||
if err != nil {
|
||||
log.Errorf("guest.SetExternalId fail %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
extVM, err := guest.GetIVM()
|
||||
if err != nil {
|
||||
log.Errorf("guest.GetIVM fail %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = guest.syncWithCloudVM(ctx, userCred, &oHost, extVM, "", false)
|
||||
if err != nil {
|
||||
log.Errorf("guest.syncWithCloudVM fail %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
idisks, err := extVM.GetIDisks()
|
||||
if err != nil {
|
||||
log.Errorf("extVM.GetIDisks fail %s", err)
|
||||
return err
|
||||
}
|
||||
|
||||
guestdisks := guest.GetDisks()
|
||||
for i := 0; i < len(guestdisks); i += 1 {
|
||||
disk := guestdisks[i].GetDisk()
|
||||
err = disk.SetExternalId(idisks[i].GetGlobalId())
|
||||
if err != nil {
|
||||
log.Errorf("disk.SetExternalId fail %s", err)
|
||||
return err
|
||||
}
|
||||
err = disk.syncWithCloudDisk(ctx, userCred, idisks[i], i, "", false)
|
||||
if err != nil {
|
||||
log.Errorf("disk.syncWithCloudDisk fail %s", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SHostManager) GetHostByRealExternalId(eid string) *SHost {
|
||||
q := manager.Query()
|
||||
q = q.Equals("real_external_id", eid)
|
||||
|
||||
host := SHost{}
|
||||
host.SetModelManager(manager)
|
||||
|
||||
err := q.First(&host)
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &host
|
||||
}
|
||||
@@ -20,7 +20,10 @@ type IHostDriver interface {
|
||||
ValidateDiskSize(storage *SStorage, sizeGb int) error
|
||||
RequestPrepareSaveDiskOnHost(ctx context.Context, host *SHost, disk *SDisk, imageId string, task taskman.ITask) error
|
||||
RequestSaveUploadImageOnHost(ctx context.Context, host *SHost, disk *SDisk, imageId string, task taskman.ITask, data jsonutils.JSONObject) error
|
||||
|
||||
RequestAllocateDiskOnStorage(ctx context.Context, host *SHost, storage *SStorage, disk *SDisk, task taskman.ITask, content *jsonutils.JSONDict) error
|
||||
RequestRebuildDiskOnStorage(ctx context.Context, host *SHost, storage *SStorage, disk *SDisk, task taskman.ITask, content *jsonutils.JSONDict) error
|
||||
|
||||
RequestDeallocateDiskOnHost(ctx context.Context, host *SHost, storage *SStorage, disk *SDisk, task taskman.ITask) error
|
||||
RequestResizeDiskOnHostOnline(ctx context.Context, host *SHost, storage *SStorage, disk *SDisk, size int64, task taskman.ITask) error
|
||||
RequestResizeDiskOnHost(ctx context.Context, host *SHost, storage *SStorage, disk *SDisk, size int64, task taskman.ITask) error
|
||||
|
||||
+99
-21
@@ -40,14 +40,16 @@ import (
|
||||
const (
|
||||
HOST_TYPE_BAREMETAL = "baremetal"
|
||||
HOST_TYPE_HYPERVISOR = "hypervisor" // KVM
|
||||
HOST_TYPE_ESXI = "esxi" // # VMWare vSphere ESXi
|
||||
HOST_TYPE_KUBELET = "kubelet" // # Kubernetes Kubelet
|
||||
HOST_TYPE_HYPERV = "hyperv" // # Microsoft Hyper-V
|
||||
HOST_TYPE_XEN = "xen" // # XenServer
|
||||
HOST_TYPE_ALIYUN = "aliyun"
|
||||
HOST_TYPE_AWS = "aws"
|
||||
HOST_TYPE_QCLOUD = "qcloud"
|
||||
HOST_TYPE_AZURE = "azure"
|
||||
HOST_TYPE_KVM = "kvm"
|
||||
HOST_TYPE_ESXI = "esxi" // # VMWare vSphere ESXi
|
||||
HOST_TYPE_KUBELET = "kubelet" // # Kubernetes Kubelet
|
||||
HOST_TYPE_HYPERV = "hyperv" // # Microsoft Hyper-V
|
||||
HOST_TYPE_XEN = "xen" // # XenServer
|
||||
|
||||
HOST_TYPE_ALIYUN = "aliyun"
|
||||
HOST_TYPE_AWS = "aws"
|
||||
HOST_TYPE_QCLOUD = "qcloud"
|
||||
HOST_TYPE_AZURE = "azure"
|
||||
|
||||
HOST_TYPE_DEFAULT = HOST_TYPE_HYPERVISOR
|
||||
|
||||
@@ -85,6 +87,13 @@ const (
|
||||
HOST_STATUS_UNKNOWN = BAREMETAL_UNKNOWN
|
||||
)
|
||||
|
||||
const (
|
||||
HostResourceTypeShared = "shared"
|
||||
HostResourceTypeDefault = HostResourceTypeShared
|
||||
HostResourceTypePrepaidRecycle = "prepaid"
|
||||
HostResourceTypeDedicated = "dedicated"
|
||||
)
|
||||
|
||||
var HOST_TYPES = []string{HOST_TYPE_BAREMETAL, HOST_TYPE_HYPERVISOR, HOST_TYPE_ESXI, HOST_TYPE_KUBELET, HOST_TYPE_XEN, HOST_TYPE_ALIYUN, HOST_TYPE_AZURE, HOST_TYPE_AWS, HOST_TYPE_QCLOUD}
|
||||
|
||||
var NIC_TYPES = []string{NIC_TYPE_IPMI, NIC_TYPE_ADMIN}
|
||||
@@ -110,6 +119,7 @@ func init() {
|
||||
type SHost struct {
|
||||
db.SEnabledStatusStandaloneResourceBase
|
||||
SManagedResourceBase
|
||||
SBillingResourceBase
|
||||
|
||||
Rack string `width:"16" charset:"ascii" nullable:"true" get:"admin" update:"admin" create:"admin_optional"` // Column(VARCHAR(16, charset='ascii'), nullable=True)
|
||||
Slots string `width:"16" charset:"ascii" nullable:"true" get:"admin" update:"admin" create:"admin_optional"` // Column(VARCHAR(16, charset='ascii'), nullable=True)
|
||||
@@ -154,6 +164,10 @@ type SHost struct {
|
||||
IsMaintenance bool `nullable:"true" default:"false" list:"admin"` // Column(Boolean, nullable=True, default=False)
|
||||
|
||||
LastPingAt time.Time ``
|
||||
|
||||
ResourceType string `width:"36" charset:"ascii" nullable:"false" list:"admin" update:"admin" create:"admin_required"` // Column(VARCHAR(36, charset='ascii'), nullable=False)
|
||||
|
||||
RealExternalId string `width:"256" charset:"utf8" get:"admin"`
|
||||
}
|
||||
|
||||
func (manager *SHostManager) GetContextManager() []db.IModelManager {
|
||||
@@ -181,6 +195,24 @@ func (self *SHost) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenC
|
||||
}
|
||||
|
||||
func (manager *SHostManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
||||
resType, _ := query.GetString("resource_type")
|
||||
if len(resType) > 0 {
|
||||
queryDict := query.(*jsonutils.JSONDict)
|
||||
queryDict.Remove("resource_type")
|
||||
|
||||
switch resType {
|
||||
case HostResourceTypeShared:
|
||||
q = q.Filter(
|
||||
sqlchemy.OR(
|
||||
sqlchemy.IsNullOrEmpty(q.Field("resource_type")),
|
||||
sqlchemy.Equals(q.Field("resource_type"), HostResourceTypeShared),
|
||||
),
|
||||
)
|
||||
default:
|
||||
q = q.Equals("resource_type", resType)
|
||||
}
|
||||
}
|
||||
|
||||
q, err := manager.SEnabledStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -1059,6 +1091,9 @@ func (manager *SHostManager) getHostsByZoneProvider(zone *SZone, provider *SClou
|
||||
if provider != nil {
|
||||
q = q.Equals("manager_id", provider.Id)
|
||||
}
|
||||
// exclude prepaid_recycle fake hosts
|
||||
q = q.NotEquals("resource_type", HostResourceTypePrepaidRecycle)
|
||||
|
||||
err := db.FetchModelObjects(manager, q, &hosts)
|
||||
if err != nil {
|
||||
log.Errorf("%s", err)
|
||||
@@ -1175,6 +1210,32 @@ func (self *SHost) syncWithCloudHost(extHost cloudprovider.ICloudHost, projectSy
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SHost) syncWithCloudPrepaidVM(extVM cloudprovider.ICloudVM, host *SHost, projectSync bool) error {
|
||||
_, err := self.SaveUpdates(func() error {
|
||||
|
||||
self.CpuCount = extVM.GetVcpuCount()
|
||||
self.MemSize = extVM.GetVmemSizeMB()
|
||||
|
||||
self.BillingType = extVM.GetBillingType()
|
||||
self.ExpiredAt = extVM.GetExpiredAt()
|
||||
|
||||
self.ExternalId = host.ExternalId
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("syncWithCloudZone error %s", err)
|
||||
}
|
||||
|
||||
if projectSync {
|
||||
if err := HostManager.ClearSchedDescCache(self.Id); err != nil {
|
||||
log.Errorf("ClearSchedDescCache for host %s error %v", self.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (manager *SHostManager) newFromCloudHost(extHost cloudprovider.ICloudHost, izone *SZone) (*SHost, error) {
|
||||
host := SHost{}
|
||||
host.SetModelManager(manager)
|
||||
@@ -1303,7 +1364,16 @@ func (self *SHost) syncWithCloudHostStorage(localStorage *SStorage, extStorage c
|
||||
return hs.syncWithCloudHostStorage(extStorage)
|
||||
}
|
||||
|
||||
func (self *SHost) isAttach2Storage(storage *SStorage) bool {
|
||||
hs := self.GetHoststorageOfId(storage.Id)
|
||||
return hs != nil
|
||||
}
|
||||
|
||||
func (self *SHost) Attach2Storage(ctx context.Context, userCred mcclient.TokenCredential, storage *SStorage, mountPoint string) error {
|
||||
if self.isAttach2Storage(storage) {
|
||||
return nil
|
||||
}
|
||||
|
||||
hs := SHoststorage{}
|
||||
hs.SetModelManager(HoststorageManager)
|
||||
|
||||
@@ -1314,6 +1384,7 @@ func (self *SHost) Attach2Storage(ctx context.Context, userCred mcclient.TokenCr
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
db.OpsLog.LogAttachEvent(self, storage, userCred, nil)
|
||||
|
||||
return nil
|
||||
@@ -1471,6 +1542,13 @@ func (self *SHost) SyncHostVMs(ctx context.Context, userCred mcclient.TokenCrede
|
||||
}
|
||||
|
||||
for i := 0; i < len(added); i += 1 {
|
||||
if added[i].GetBillingType() == BILLING_TYPE_PREPAID {
|
||||
vhost := HostManager.GetHostByRealExternalId(added[i].GetGlobalId())
|
||||
if vhost != nil {
|
||||
// this recycle vm is not build yet, skip synchronize
|
||||
continue
|
||||
}
|
||||
}
|
||||
new, err := GuestManager.newCloudVM(ctx, userCred, self, added[i], projectId)
|
||||
if err != nil {
|
||||
syncResult.AddError(err)
|
||||
@@ -1607,6 +1685,8 @@ func (manager *SHostManager) totalCountQ(
|
||||
rangeObj db.IStandaloneModel,
|
||||
hostStatus, status string,
|
||||
hostTypes []string,
|
||||
resourceTypes []string,
|
||||
providers []string,
|
||||
enabled, isBaremetal tristate.TriState,
|
||||
) *sqlchemy.SQuery {
|
||||
hosts := manager.Query().SubQuery()
|
||||
@@ -1631,7 +1711,7 @@ func (manager *SHostManager) totalCountQ(
|
||||
}
|
||||
q = q.Filter(cond(hosts.Field("is_baremetal")))
|
||||
}
|
||||
q = AttachUsageQuery(q, hosts, hosts.Field("id"), hostTypes, rangeObj)
|
||||
q = AttachUsageQuery(q, hosts, hostTypes, resourceTypes, providers, rangeObj)
|
||||
return q
|
||||
}
|
||||
|
||||
@@ -1708,25 +1788,16 @@ func (manager *SHostManager) calculateCount(q *sqlchemy.SQuery) HostsCountStat {
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *SHostManager) totalCount(
|
||||
userCred mcclient.TokenCredential,
|
||||
rangeObj db.IStandaloneModel,
|
||||
hostStatus, status string,
|
||||
hostTypes []string,
|
||||
enabled, isBaremetal tristate.TriState,
|
||||
) HostsCountStat {
|
||||
return manager.calculateCount(manager.totalCountQ(userCred, rangeObj, hostStatus, status, hostTypes, enabled, isBaremetal))
|
||||
}
|
||||
|
||||
func (manager *SHostManager) TotalCount(
|
||||
userCred mcclient.TokenCredential,
|
||||
rangeObj db.IStandaloneModel,
|
||||
hostStatus, status string,
|
||||
hostTypes []string,
|
||||
resourceTypes []string,
|
||||
providers []string,
|
||||
enabled, isBaremetal tristate.TriState,
|
||||
) HostsCountStat {
|
||||
stat1 := manager.totalCount(userCred, rangeObj, hostStatus, status, hostTypes, enabled, isBaremetal)
|
||||
return stat1
|
||||
return manager.calculateCount(manager.totalCountQ(userCred, rangeObj, hostStatus, status, hostTypes, resourceTypes, providers, enabled, isBaremetal))
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1930,6 +2001,13 @@ func (self *SHost) getMoreDetails(ctx context.Context, extra *jsonutils.JSONDict
|
||||
extra.Add(jsonutils.NewFloat(memCommitRate), "mem_commit_rate")
|
||||
extra.Add(self.GetHardwareSpecification(), "spec")
|
||||
extra = self.SManagedResourceBase.getExtraDetails(ctx, extra)
|
||||
|
||||
if self.IsPrepaidRecycle() {
|
||||
extra.Add(jsonutils.JSONTrue, "is_prepaid_recycle")
|
||||
} else {
|
||||
extra.Add(jsonutils.JSONFalse, "is_prepaid_recycle")
|
||||
}
|
||||
|
||||
return extra
|
||||
}
|
||||
|
||||
|
||||
@@ -385,20 +385,18 @@ func (manager *SIsolatedDeviceManager) ReleaseDevicesOfGuest(guest *SGuest, user
|
||||
}
|
||||
|
||||
func (manager *SIsolatedDeviceManager) totalCountQ(
|
||||
devType, hostTypes []string,
|
||||
devType []string, hostTypes []string,
|
||||
resourceTypes []string, providers []string,
|
||||
rangeObj db.IStandaloneModel,
|
||||
) *sqlchemy.SQuery {
|
||||
hosts := HostManager.Query().SubQuery()
|
||||
q := manager.Query().Join(hosts, sqlchemy.AND(
|
||||
sqlchemy.IsFalse(hosts.Field("deleted")),
|
||||
sqlchemy.IsTrue(hosts.Field("enabled")),
|
||||
))
|
||||
q = q.Filter(sqlchemy.Equals(hosts.Field("id"), q.Field("host_id")))
|
||||
if len(devType) != 0 {
|
||||
q.In("dev_type", devType)
|
||||
}
|
||||
devs := manager.Query().SubQuery()
|
||||
return AttachUsageQuery(q, hosts, devs.Field("host_id"), hostTypes, rangeObj)
|
||||
q := devs.Query().Join(hosts, sqlchemy.Equals(devs.Field("host_id"), hosts.Field("id")))
|
||||
q = q.Filter(sqlchemy.IsTrue(hosts.Field("enabled")))
|
||||
if len(devType) != 0 {
|
||||
q = q.Filter(sqlchemy.In(devs.Field("dev_type"), devType))
|
||||
}
|
||||
return AttachUsageQuery(q, hosts, hostTypes, resourceTypes, providers, rangeObj)
|
||||
}
|
||||
|
||||
type IsolatedDeviceCountStat struct {
|
||||
@@ -406,14 +404,14 @@ type IsolatedDeviceCountStat struct {
|
||||
Gpus int
|
||||
}
|
||||
|
||||
func (manager *SIsolatedDeviceManager) totalCount(devType, hostTypes []string, rangeObj db.IStandaloneModel) int {
|
||||
return manager.totalCountQ(devType, hostTypes, rangeObj).Count()
|
||||
func (manager *SIsolatedDeviceManager) totalCount(devType, hostTypes []string, resourceTypes []string, providers []string, rangeObj db.IStandaloneModel) int {
|
||||
return manager.totalCountQ(devType, hostTypes, resourceTypes, providers, rangeObj).Count()
|
||||
}
|
||||
|
||||
func (manager *SIsolatedDeviceManager) TotalCount(hostType []string, rangeObj db.IStandaloneModel) IsolatedDeviceCountStat {
|
||||
func (manager *SIsolatedDeviceManager) TotalCount(hostType []string, resourceTypes []string, providers []string, rangeObj db.IStandaloneModel) IsolatedDeviceCountStat {
|
||||
return IsolatedDeviceCountStat{
|
||||
Devices: manager.totalCount(nil, hostType, rangeObj),
|
||||
Gpus: manager.totalCount(VALID_GPU_TYPES, hostType, rangeObj),
|
||||
Devices: manager.totalCount(nil, hostType, resourceTypes, providers, rangeObj),
|
||||
Gpus: manager.totalCount(VALID_GPU_TYPES, hostType, resourceTypes, providers, rangeObj),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -270,7 +270,7 @@ func (man *SLoadbalancerAgentManager) ValidateCreateData(ctx context.Context, us
|
||||
return man.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data)
|
||||
}
|
||||
|
||||
func (man *SLoadbalancerAgentManager) CleanPendingDeleteLoadbalancers(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
func (man *SLoadbalancerAgentManager) CleanPendingDeleteLoadbalancers(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
agents := []SLoadbalancerAgent{}
|
||||
{
|
||||
// find active agents
|
||||
|
||||
@@ -35,6 +35,14 @@ func (self *SManagedResourceBase) GetDriver() (cloudprovider.ICloudProvider, err
|
||||
return provider.GetDriver()
|
||||
}
|
||||
|
||||
func (self *SManagedResourceBase) GetProviderName() string {
|
||||
driver := self.GetCloudprovider()
|
||||
if driver != nil {
|
||||
return driver.Provider
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SManagedResourceBase) IsManaged() bool {
|
||||
return len(self.ManagerId) > 0
|
||||
}
|
||||
|
||||
@@ -189,9 +189,6 @@ func (self *SNetInterface) getServerJsonDesc() *jsonutils.JSONDict {
|
||||
|
||||
func (self *SNetInterface) getBaremetalJsonDesc() *jsonutils.JSONDict {
|
||||
bn := self.GetBaremetalNetwork()
|
||||
if bn == nil {
|
||||
return nil
|
||||
}
|
||||
return self.hostNetworkToJson(bn)
|
||||
}
|
||||
|
||||
|
||||
@@ -606,26 +606,22 @@ func (manager *SNetworkManager) GetNetworkOfIP(ipAddr string, serverType string,
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
|
||||
func (manager *SNetworkManager) allNetworksQ(rangeObj db.IStandaloneModel) *sqlchemy.SQuery {
|
||||
func (manager *SNetworkManager) allNetworksQ(providers []string, rangeObj db.IStandaloneModel) *sqlchemy.SQuery {
|
||||
networks := manager.Query().SubQuery()
|
||||
hostwires := HostwireManager.Query().SubQuery()
|
||||
hosts := HostManager.Query().SubQuery()
|
||||
q := networks.Query().
|
||||
Join(hostwires, sqlchemy.AND(
|
||||
sqlchemy.Equals(hostwires.Field("wire_id"), networks.Field("wire_id")),
|
||||
sqlchemy.IsFalse(hostwires.Field("deleted")))).
|
||||
Join(hosts, sqlchemy.AND(
|
||||
sqlchemy.Equals(hosts.Field("id"), hostwires.Field("host_id")),
|
||||
sqlchemy.IsFalse(hosts.Field("deleted")),
|
||||
sqlchemy.IsTrue(hosts.Field("enabled")),
|
||||
sqlchemy.OR(
|
||||
sqlchemy.Equals(hosts.Field("host_type"), HOST_TYPE_BAREMETAL),
|
||||
sqlchemy.Equals(hosts.Field("host_status"), HOST_ONLINE))))
|
||||
return AttachUsageQuery(q, hosts, hostwires.Field("host_id"), nil, rangeObj)
|
||||
q := networks.Query()
|
||||
q = q.Join(hostwires, sqlchemy.Equals(hostwires.Field("wire_id"), networks.Field("wire_id")))
|
||||
q = q.Join(hosts, sqlchemy.Equals(hosts.Field("id"), hostwires.Field("host_id")))
|
||||
q = q.Filter(sqlchemy.IsTrue(hosts.Field("enabled")))
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.Equals(hosts.Field("host_type"), HOST_TYPE_BAREMETAL),
|
||||
sqlchemy.Equals(hosts.Field("host_status"), HOST_ONLINE)))
|
||||
return AttachUsageQuery(q, hosts, nil, nil, providers, rangeObj)
|
||||
}
|
||||
|
||||
func (manager *SNetworkManager) totalPortCountQ(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel) *sqlchemy.SQuery {
|
||||
q := manager.allNetworksQ(rangeObj)
|
||||
func (manager *SNetworkManager) totalPortCountQ(userCred mcclient.TokenCredential, providers []string, rangeObj db.IStandaloneModel) *sqlchemy.SQuery {
|
||||
q := manager.allNetworksQ(providers, rangeObj)
|
||||
networks := manager.Query().SubQuery()
|
||||
if userCred != nil && !db.IsAdminAllowList(userCred, manager) {
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
@@ -640,9 +636,9 @@ type NetworkPortStat struct {
|
||||
CountExt int
|
||||
}
|
||||
|
||||
func (manager *SNetworkManager) TotalPortCount(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel) NetworkPortStat {
|
||||
func (manager *SNetworkManager) TotalPortCount(userCred mcclient.TokenCredential, providers []string, rangeObj db.IStandaloneModel) NetworkPortStat {
|
||||
nets := make([]SNetwork, 0)
|
||||
err := manager.totalPortCountQ(userCred, rangeObj).All(&nets)
|
||||
err := manager.totalPortCountQ(userCred, providers, rangeObj).All(&nets)
|
||||
if err != nil {
|
||||
log.Errorf("TotalPortCount: %v", err)
|
||||
}
|
||||
|
||||
@@ -75,9 +75,9 @@ func (self *SQuota) FetchSystemQuota() {
|
||||
func (self *SQuota) FetchUsage(projectId string) error {
|
||||
diskSize := totalDiskSize(projectId, tristate.None, tristate.None, false)
|
||||
net := totalGuestNicCount(projectId, nil, false)
|
||||
guest := totalGuestResourceCount(projectId, nil, nil, nil, false, false, "")
|
||||
guest := totalGuestResourceCount(projectId, nil, nil, nil, false, false, nil, nil, nil)
|
||||
eipUsage := ElasticipManager.TotalCount(projectId, nil, nil)
|
||||
snapshotCount := totalSnapshotCount(projectId)
|
||||
snapshotCount := TotalSnapshotCount(projectId, nil, nil)
|
||||
// XXX
|
||||
// keypair belongs to user
|
||||
// keypair := totalKeypairCount(projectId)
|
||||
|
||||
+132
-21
@@ -78,11 +78,14 @@ type SServerSku struct {
|
||||
|
||||
CloudregionId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"admin_required" update:"admin"`
|
||||
ZoneId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"admin_optional" update:"admin"`
|
||||
Provider string `width:"64" charset:"ascii" nullable:"false" list:"user" create:"admin_optional" update:"admin"`
|
||||
Provider string `width:"64" charset:"ascii" nullable:"true" list:"user" create:"admin_optional" update:"admin"`
|
||||
}
|
||||
|
||||
func inWhiteList(provider string) bool {
|
||||
// 只有为true的hypervisor才进行创建和更新操作
|
||||
if len(provider) == 0 {
|
||||
return true
|
||||
}
|
||||
switch provider {
|
||||
case HYPERVISOR_ESXI, HYPERVISOR_KVM:
|
||||
return true
|
||||
@@ -99,19 +102,21 @@ func (self *SServerSku) AllowGetDetails(ctx context.Context, userCred mcclient.T
|
||||
return true
|
||||
}
|
||||
|
||||
func (manager *SServerSkuManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return db.IsAdminAllowCreate(userCred, manager)
|
||||
}
|
||||
|
||||
func (self *SServerSkuManager) ValidateCreateData(ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
ownerProjId string,
|
||||
query jsonutils.JSONObject,
|
||||
data *jsonutils.JSONDict,
|
||||
) (*jsonutils.JSONDict, error) {
|
||||
provider, err := data.GetString("provider")
|
||||
if err != nil || len(provider) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("provider")
|
||||
}
|
||||
|
||||
provider, _ := data.GetString("provider")
|
||||
|
||||
if !inWhiteList(provider) {
|
||||
return nil, httperrors.NewInputParameterError("can not create with provider %s", provider)
|
||||
return nil, httperrors.NewForbiddenError("can not create instance_type for public cloud %s", provider)
|
||||
}
|
||||
|
||||
regionStr := jsonutils.GetAnyString(data, []string{"region", "region_id", "cloudregion", "cloudregion_id"})
|
||||
@@ -179,7 +184,7 @@ func (self *SServerSkuManager) GetPropertyInstanceSpecs(ctx context.Context, use
|
||||
q := self.Query()
|
||||
zone, err := query.GetString("zone")
|
||||
if err == nil && len(zone) > 0 {
|
||||
q = q.Equals("zone", zone)
|
||||
q = q.Equals("zone_id", zone)
|
||||
} else {
|
||||
return nil, httperrors.NewMissingParameterError("zone")
|
||||
}
|
||||
@@ -240,11 +245,7 @@ func (self *SServerSkuManager) GetPropertyInstanceSpecs(ctx context.Context, use
|
||||
}
|
||||
|
||||
func (self *SServerSku) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
|
||||
if self.SStandaloneResourceBase.AllowUpdateItem(ctx, userCred) == false {
|
||||
return false
|
||||
}
|
||||
|
||||
return inWhiteList(self.Provider)
|
||||
return inWhiteList(self.Provider) && db.IsAdminAllowUpdate(userCred, self)
|
||||
}
|
||||
|
||||
func (self *SServerSku) ValidateUpdateData(
|
||||
@@ -252,9 +253,14 @@ func (self *SServerSku) ValidateUpdateData(
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
|
||||
if !inWhiteList(self.Provider) {
|
||||
return nil, httperrors.NewForbiddenError("can not create instance_type for public cloud %s", self.Provider)
|
||||
}
|
||||
|
||||
provider, err := data.GetString("provider")
|
||||
if err == nil && !inWhiteList(provider) {
|
||||
return nil, httperrors.NewInputParameterError("can not create with provider %s", provider)
|
||||
return nil, httperrors.NewForbiddenError("can not create instance_type for public cloud %s", provider)
|
||||
}
|
||||
|
||||
zoneStr := jsonutils.GetAnyString(data, []string{"zone", "zone_id"})
|
||||
@@ -272,16 +278,18 @@ func (self *SServerSku) ValidateUpdateData(
|
||||
}
|
||||
|
||||
func (self *SServerSku) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
if !inWhiteList(self.Provider) {
|
||||
return false
|
||||
}
|
||||
return inWhiteList(self.Provider) && db.IsAdminAllowDelete(userCred, self)
|
||||
}
|
||||
|
||||
count := GuestManager.Query().Equals("sku_id", self.Id).Count()
|
||||
if count == 0 {
|
||||
return self.SStandaloneResourceBase.AllowDeleteItem(ctx, userCred, query, data)
|
||||
} else {
|
||||
return false
|
||||
func (self *SServerSku) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if !inWhiteList(self.Provider) {
|
||||
return httperrors.NewForbiddenError("not allow to delete public cloud instance_type: %s", self.Name)
|
||||
}
|
||||
count := GuestManager.Query().Equals("instance_type", self.Name).Count()
|
||||
if count > 0 {
|
||||
return httperrors.NewNotEmptyError("instance_type used by servers")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SServerSku) GetZoneExternalId() (string, error) {
|
||||
@@ -293,3 +301,106 @@ func (self *SServerSku) GetZoneExternalId() (string, error) {
|
||||
zone := zoneObj.(*SZone)
|
||||
return zone.GetExternalId(), nil
|
||||
}
|
||||
|
||||
func (manager *SServerSkuManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
||||
queryDict := query.(*jsonutils.JSONDict)
|
||||
|
||||
provider := jsonutils.GetAnyString(query, []string{"provider"})
|
||||
if len(provider) > 0 {
|
||||
if provider != "all" {
|
||||
q = q.Equals("provider", provider)
|
||||
}
|
||||
|
||||
queryDict.Remove("provider")
|
||||
} else {
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.IsNull(q.Field("provider")),
|
||||
sqlchemy.IsEmpty(q.Field("provider")),
|
||||
))
|
||||
}
|
||||
|
||||
q, err := manager.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
regionStr := jsonutils.GetAnyString(query, []string{"region", "cloudregion", "region_id", "cloudregion_id"})
|
||||
if len(regionStr) > 0 {
|
||||
regionObj, err := CloudregionManager.FetchByIdOrName(nil, regionStr)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(CloudregionManager.Keyword(), regionStr)
|
||||
}
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
q = q.Equals("cloudregion_id", regionObj.GetId())
|
||||
}
|
||||
|
||||
zoneStr := jsonutils.GetAnyString(query, []string{"zone", "zone_id"})
|
||||
if len(zoneStr) > 0 {
|
||||
zoneObj, err := ZoneManager.FetchByIdOrName(nil, zoneStr)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(ZoneManager.Keyword(), zoneStr)
|
||||
}
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
q = q.Equals("zone_id", zoneObj.GetId())
|
||||
}
|
||||
|
||||
return q, err
|
||||
}
|
||||
|
||||
func (manager *SServerSkuManager) FetchSkuByNameAndHypervisor(name string, hypervisor string, checkConsistency bool) (*SServerSku, error) {
|
||||
q := manager.Query()
|
||||
q = q.Equals("name", name)
|
||||
if len(hypervisor) > 0 {
|
||||
switch hypervisor {
|
||||
case HYPERVISOR_BAREMETAL, HYPERVISOR_CONTAINER:
|
||||
return nil, httperrors.NewNotImplementedError("%s not supported", hypervisor)
|
||||
case HYPERVISOR_KVM, HYPERVISOR_ESXI, HYPERVISOR_XEN, HOST_TYPE_HYPERV:
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.IsEmpty(q.Field("provider")),
|
||||
sqlchemy.IsNull(q.Field("provider")),
|
||||
sqlchemy.Equals(q.Field("provider"), hypervisor),
|
||||
))
|
||||
default:
|
||||
q = q.Equals("provider", hypervisor)
|
||||
}
|
||||
} else {
|
||||
q = q.IsEmpty("provider")
|
||||
}
|
||||
skus := make([]SServerSku, 0)
|
||||
err := db.FetchModelObjects(manager, q, &skus)
|
||||
if err != nil {
|
||||
log.Errorf("fetch sku fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
if len(skus) == 0 {
|
||||
log.Errorf("no sku found for %s %s", name, hypervisor)
|
||||
return nil, httperrors.NewResourceNotFoundError2(manager.Keyword(), name)
|
||||
}
|
||||
if len(skus) == 1 {
|
||||
return &skus[0], nil
|
||||
}
|
||||
if checkConsistency {
|
||||
for i := 1; i < len(skus); i += 1 {
|
||||
if skus[i].CpuCoreCount != skus[0].CpuCoreCount || skus[i].MemorySizeMB != skus[0].MemorySizeMB {
|
||||
log.Errorf("inconsistent sku %s %s", jsonutils.Marshal(&skus[0]), jsonutils.Marshal(&skus[i]))
|
||||
return nil, httperrors.NewDuplicateResourceError("duplicate instanceType %s", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return &skus[0], nil
|
||||
}
|
||||
|
||||
func (manager *SServerSkuManager) GetSkuCountByProvider(provider string) int {
|
||||
q := manager.Query()
|
||||
if len(provider) == 0 {
|
||||
q = q.IsNotEmpty("provider")
|
||||
} else {
|
||||
q = q.Equals("provider", provider)
|
||||
}
|
||||
|
||||
return q.Count()
|
||||
}
|
||||
|
||||
@@ -456,10 +456,31 @@ func (self *SSnapshot) Delete(ctx context.Context, userCred mcclient.TokenCreden
|
||||
return nil
|
||||
}
|
||||
|
||||
func totalSnapshotCount(projectId string) int {
|
||||
func TotalSnapshotCount(projectId string, rangeObj db.IStandaloneModel, providers []string) int {
|
||||
q := SnapshotManager.Query()
|
||||
count := q.Equals("tenant_id", projectId).Equals("fake_deleted", false).Count()
|
||||
return count
|
||||
if len(projectId) > 0 {
|
||||
q = q.Equals("tenant_id", projectId)
|
||||
}
|
||||
if rangeObj != nil {
|
||||
switch rangeObj.Keyword() {
|
||||
case "cloudprovider":
|
||||
q = q.Filter(sqlchemy.Equals(q.Field("manager_id"), rangeObj.GetId()))
|
||||
case "cloudaccount":
|
||||
cloudproviders := CloudproviderManager.Query().SubQuery()
|
||||
subq := cloudproviders.Query(cloudproviders.Field("id")).Equals("cloudaccount_id", rangeObj.GetId()).SubQuery()
|
||||
q = q.Filter(sqlchemy.In(q.Field("manager_id"), subq))
|
||||
case "cloudregion":
|
||||
q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), rangeObj.GetId()))
|
||||
}
|
||||
}
|
||||
if len(providers) > 0 {
|
||||
cloudproviders := CloudproviderManager.Query().SubQuery()
|
||||
subq := cloudproviders.Query(cloudproviders.Field("id"))
|
||||
subq = subq.In("provider", providers)
|
||||
q = q.In("manager_id", subq.SubQuery())
|
||||
}
|
||||
q = q.Equals("fake_deleted", false)
|
||||
return q.Count()
|
||||
}
|
||||
|
||||
// Only sync snapshot status
|
||||
|
||||
@@ -800,6 +800,7 @@ func (manager *SStorageManager) disksFailedQ() *sqlchemy.SSubQuery {
|
||||
|
||||
func (manager *SStorageManager) totalCapacityQ(
|
||||
rangeObj db.IStandaloneModel, hostTypes []string,
|
||||
resourceTypes []string, providers []string,
|
||||
) *sqlchemy.SQuery {
|
||||
stmt := manager.disksReadyQ()
|
||||
stmt2 := manager.disksFailedQ()
|
||||
@@ -814,26 +815,32 @@ func (manager *SStorageManager) totalCapacityQ(
|
||||
stmt2.Field("failed_capacity"),
|
||||
attachedDisks.Field("attached_used_capacity"),
|
||||
detachedDisks.Field("detached_used_capacity"),
|
||||
).
|
||||
LeftJoin(stmt, sqlchemy.Equals(stmt.Field("storage_id"), storages.Field("id"))).
|
||||
LeftJoin(stmt2, sqlchemy.Equals(stmt2.Field("storage_id"), storages.Field("id"))).
|
||||
LeftJoin(attachedDisks, sqlchemy.Equals(attachedDisks.Field("storage_id"), storages.Field("id"))).
|
||||
LeftJoin(detachedDisks, sqlchemy.Equals(detachedDisks.Field("storage_id"), storages.Field("id")))
|
||||
)
|
||||
q = q.LeftJoin(stmt, sqlchemy.Equals(stmt.Field("storage_id"), storages.Field("id")))
|
||||
q = q.LeftJoin(stmt2, sqlchemy.Equals(stmt2.Field("storage_id"), storages.Field("id")))
|
||||
q = q.LeftJoin(attachedDisks, sqlchemy.Equals(attachedDisks.Field("storage_id"), storages.Field("id")))
|
||||
q = q.LeftJoin(detachedDisks, sqlchemy.Equals(detachedDisks.Field("storage_id"), storages.Field("id")))
|
||||
|
||||
hosts := HostManager.Query().SubQuery()
|
||||
hostStorages := HoststorageManager.Query().SubQuery()
|
||||
if len(hostTypes) > 0 || len(resourceTypes) > 0 || rangeObj != nil {
|
||||
hosts := HostManager.Query().SubQuery()
|
||||
hostStorages := HoststorageManager.Query().SubQuery()
|
||||
|
||||
q = q.Join(hostStorages, sqlchemy.AND(
|
||||
sqlchemy.Equals(hostStorages.Field("storage_id"), storages.Field("id")),
|
||||
sqlchemy.IsFalse(hostStorages.Field("deleted")),
|
||||
)).Join(
|
||||
hosts, sqlchemy.AND(
|
||||
sqlchemy.Equals(hosts.Field("id"), hostStorages.Field("host_id")),
|
||||
sqlchemy.IsFalse(hosts.Field("deleted")),
|
||||
sqlchemy.IsTrue(hosts.Field("enabled")),
|
||||
sqlchemy.Equals(hosts.Field("host_status"), HOST_ONLINE)))
|
||||
q = q.Join(hostStorages, sqlchemy.Equals(hostStorages.Field("storage_id"), storages.Field("id")))
|
||||
q = q.Join(hosts, sqlchemy.Equals(hosts.Field("id"), hostStorages.Field("host_id")))
|
||||
q = q.Filter(sqlchemy.IsTrue(hosts.Field("enabled")))
|
||||
q = q.Filter(sqlchemy.Equals(hosts.Field("host_status"), HOST_ONLINE))
|
||||
|
||||
return AttachUsageQuery(q, hosts, hostStorages.Field("host_id"), hostTypes, rangeObj)
|
||||
q = AttachUsageQuery(q, hosts, hostTypes, resourceTypes, nil, rangeObj)
|
||||
}
|
||||
|
||||
if len(providers) > 0 {
|
||||
cloudproviders := CloudproviderManager.Query().SubQuery()
|
||||
subq := cloudproviders.Query(cloudproviders.Field("id"))
|
||||
subq = subq.Filter(sqlchemy.In(cloudproviders.Field("provider"), providers))
|
||||
q = q.Filter(sqlchemy.In(storages.Field("manager_id"), subq.SubQuery()))
|
||||
}
|
||||
|
||||
return q
|
||||
}
|
||||
|
||||
type StorageStat struct {
|
||||
@@ -850,7 +857,7 @@ type StoragesCapacityStat struct {
|
||||
Capacity int64
|
||||
CapacityVirtual float64
|
||||
CapacityUsed int64
|
||||
CapacityUnread int64
|
||||
CapacityUnready int64
|
||||
AttachedCapacity int64
|
||||
DetachedCapacity int64
|
||||
}
|
||||
@@ -884,18 +891,21 @@ func (manager *SStorageManager) calculateCapacity(q *sqlchemy.SQuery) StoragesCa
|
||||
Capacity: tCapa,
|
||||
CapacityVirtual: tVCapa,
|
||||
CapacityUsed: tUsed,
|
||||
CapacityUnread: tFailed,
|
||||
CapacityUnready: tFailed,
|
||||
AttachedCapacity: atCapa,
|
||||
DetachedCapacity: dtCapa,
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *SStorageManager) TotalCapacity(rangeObj db.IStandaloneModel, hostTypes []string) StoragesCapacityStat {
|
||||
res1 := manager.calculateCapacity(manager.totalCapacityQ(rangeObj, hostTypes))
|
||||
func (manager *SStorageManager) TotalCapacity(rangeObj db.IStandaloneModel, hostTypes []string, resourceTypes []string, providers []string) StoragesCapacityStat {
|
||||
res1 := manager.calculateCapacity(manager.totalCapacityQ(rangeObj, hostTypes, resourceTypes, providers))
|
||||
return res1
|
||||
}
|
||||
|
||||
func (self *SStorage) createDisk(name string, diskConfig *SDiskConfig, userCred mcclient.TokenCredential, ownerProjId string, autoDelete bool, isSystem bool) (*SDisk, error) {
|
||||
func (self *SStorage) createDisk(name string, diskConfig *SDiskConfig, userCred mcclient.TokenCredential,
|
||||
ownerProjId string, autoDelete bool, isSystem bool,
|
||||
billingType string, billingCycle string,
|
||||
) (*SDisk, error) {
|
||||
disk := SDisk{}
|
||||
disk.SetModelManager(DiskManager)
|
||||
|
||||
@@ -907,6 +917,9 @@ func (self *SStorage) createDisk(name string, diskConfig *SDiskConfig, userCred
|
||||
disk.ProjectId = ownerProjId
|
||||
disk.IsSystem = isSystem
|
||||
|
||||
disk.BillingType = billingType
|
||||
disk.BillingCycle = billingCycle
|
||||
|
||||
err := disk.GetModelManager().TableSpec().Insert(&disk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
+35
-15
@@ -1,51 +1,71 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/pkg/utils"
|
||||
)
|
||||
|
||||
func AttachUsageQuery(
|
||||
q *sqlchemy.SQuery,
|
||||
hosts *sqlchemy.SSubQuery,
|
||||
hostIdField sqlchemy.IQueryField,
|
||||
hostTypes []string,
|
||||
resourceTypes []string,
|
||||
providers []string,
|
||||
rangeObj db.IStandaloneModel,
|
||||
) *sqlchemy.SQuery {
|
||||
if len(hostTypes) != 0 {
|
||||
if len(hostTypes) > 0 {
|
||||
q = q.Filter(sqlchemy.In(hosts.Field("host_type"), hostTypes))
|
||||
}
|
||||
if len(resourceTypes) > 0 {
|
||||
if utils.IsInStringArray(HostResourceTypeShared, resourceTypes) {
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.IsNullOrEmpty(hosts.Field("resource_type")),
|
||||
sqlchemy.In(hosts.Field("resource_type"), resourceTypes),
|
||||
))
|
||||
} else {
|
||||
q = q.Filter(sqlchemy.In(hosts.Field("resource_type"), resourceTypes))
|
||||
}
|
||||
}
|
||||
if len(providers) > 0 {
|
||||
cloudproviders := CloudproviderManager.Query().SubQuery()
|
||||
subq := cloudproviders.Query(cloudproviders.Field("id")).In("provider", providers).SubQuery()
|
||||
q = q.Filter(sqlchemy.In(hosts.Field("manager_id"), subq))
|
||||
}
|
||||
if rangeObj == nil {
|
||||
return q
|
||||
}
|
||||
rangeObjId := rangeObj.GetId()
|
||||
//rangeObjId := rangeObj.GetId()
|
||||
kw := rangeObj.Keyword()
|
||||
log.Debugf("rangeObj keyword: %s", kw)
|
||||
// log.Debugf("rangeObj keyword: %s", kw)
|
||||
switch kw {
|
||||
case "zone":
|
||||
q = q.Filter(sqlchemy.Equals(hosts.Field("zone_id"), rangeObjId))
|
||||
zone := rangeObj.(*SZone)
|
||||
q = q.Filter(sqlchemy.Equals(hosts.Field("zone_id"), zone.Id))
|
||||
case "wire":
|
||||
wire := rangeObj.(*SWire)
|
||||
hostWires := HostwireManager.Query().SubQuery()
|
||||
q = q.Join(hostWires, sqlchemy.AND(
|
||||
sqlchemy.Equals(hosts.Field("id"), hostWires.Field("host_id")),
|
||||
sqlchemy.IsFalse(hostWires.Field("deleted")))).
|
||||
Filter(sqlchemy.Equals(hostWires.Field("wire_id"), rangeObjId))
|
||||
subq := hostWires.Query(hostWires.Field("host_id")).Equals("wire_id", wire.Id).SubQuery()
|
||||
q = q.Filter(sqlchemy.In(hosts.Field("id"), subq))
|
||||
case "host":
|
||||
q = q.Filter(sqlchemy.Equals(hostIdField, rangeObjId))
|
||||
case "vcenter":
|
||||
q = q.Filter(sqlchemy.Equals(hosts.Field("manager_id"), rangeObjId))
|
||||
q = q.Filter(sqlchemy.Equals(hosts.Field("id"), rangeObj.GetId()))
|
||||
case "cloudprovider":
|
||||
q = q.Filter(sqlchemy.Equals(hosts.Field("manager_id"), rangeObj.GetId()))
|
||||
case "cloudaccount":
|
||||
cloudproviders := CloudproviderManager.Query().SubQuery()
|
||||
subq := cloudproviders.Query(cloudproviders.Field("id")).Equals("cloudaccount_id", rangeObj.GetId()).SubQuery()
|
||||
q = q.Filter(sqlchemy.In(hosts.Field("manager_id"), subq))
|
||||
case "schedtag":
|
||||
aggHosts := HostschedtagManager.Query().SubQuery()
|
||||
q = q.Join(aggHosts, sqlchemy.AND(
|
||||
sqlchemy.Equals(hosts.Field("id"), aggHosts.Field("host_id")),
|
||||
sqlchemy.IsFalse(aggHosts.Field("deleted")))).
|
||||
Filter(sqlchemy.Equals(aggHosts.Field("schedtag_id"), rangeObjId))
|
||||
Filter(sqlchemy.Equals(aggHosts.Field("schedtag_id"), rangeObj.GetId()))
|
||||
case "cloudregion":
|
||||
zones := ZoneManager.Query().SubQuery()
|
||||
q = q.Join(zones, sqlchemy.Equals(hosts.Field("zone_id"), zones.Field("id")))
|
||||
q = q.Filter(sqlchemy.Equals(zones.Field("cloudregion_id"), rangeObjId))
|
||||
q = q.Filter(sqlchemy.Equals(zones.Field("cloudregion_id"), rangeObj.GetId()))
|
||||
}
|
||||
return q
|
||||
}
|
||||
|
||||
+43
-36
@@ -275,30 +275,26 @@ func (manager *SWireManager) newFromCloudWire(extWire cloudprovider.ICloudWire,
|
||||
return &wire, nil
|
||||
}
|
||||
|
||||
func (manager *SWireManager) totalCountQ(rangeObj db.IStandaloneModel, hostTypes []string) *sqlchemy.SQuery {
|
||||
func (manager *SWireManager) totalCountQ(rangeObj db.IStandaloneModel, hostTypes []string, providers []string) *sqlchemy.SQuery {
|
||||
guests := GuestManager.Query().SubQuery()
|
||||
hosts := HostManager.Query().SubQuery()
|
||||
|
||||
gNics := GuestnetworkManager.Query().SubQuery()
|
||||
gNicQ := gNics.Query(
|
||||
gNics.Field("network_id"),
|
||||
sqlchemy.COUNT("id").Label("gnic_count")).
|
||||
Join(guests, sqlchemy.AND(
|
||||
sqlchemy.IsFalse(guests.Field("deleted")),
|
||||
sqlchemy.Equals(guests.Field("id"), gNics.Field("guest_id")),
|
||||
)).
|
||||
Join(hosts, sqlchemy.AND(
|
||||
sqlchemy.Equals(guests.Field("host_id"), hosts.Field("id")),
|
||||
sqlchemy.IsFalse(hosts.Field("deleted")),
|
||||
sqlchemy.IsTrue(hosts.Field("enabled"))))
|
||||
sqlchemy.COUNT("id").Label("gnic_count"),
|
||||
)
|
||||
gNicQ = gNicQ.Join(guests, sqlchemy.Equals(guests.Field("id"), gNics.Field("guest_id")))
|
||||
gNicQ = gNicQ.Join(hosts, sqlchemy.Equals(guests.Field("host_id"), hosts.Field("id")))
|
||||
gNicQ = gNicQ.Filter(sqlchemy.IsTrue(hosts.Field("enabled")))
|
||||
|
||||
hNics := HostnetworkManager.Query().SubQuery()
|
||||
hNicQ := hNics.Query(
|
||||
hNics.Field("network_id"),
|
||||
sqlchemy.COUNT("id").Label("hnic_count")).
|
||||
Join(hosts, sqlchemy.AND(
|
||||
sqlchemy.Equals(hNics.Field("baremetal_id"), hosts.Field("id")),
|
||||
sqlchemy.IsFalse(hosts.Field("deleted")),
|
||||
sqlchemy.IsTrue(hosts.Field("enabled"))))
|
||||
sqlchemy.COUNT("id").Label("hnic_count"),
|
||||
)
|
||||
hNicQ = hNicQ.Join(hosts, sqlchemy.Equals(hNics.Field("baremetal_id"), hosts.Field("id")))
|
||||
hNicQ = hNicQ.Filter(sqlchemy.IsTrue(hosts.Field("enabled")))
|
||||
|
||||
revIps := ReservedipManager.Query().SubQuery()
|
||||
revQ := revIps.Query(revIps.Field("network_id"), sqlchemy.COUNT("id").Label("rnic_count"))
|
||||
@@ -313,30 +309,41 @@ func (manager *SWireManager) totalCountQ(rangeObj db.IStandaloneModel, hostTypes
|
||||
sqlchemy.COUNT("id").Label("net_count"),
|
||||
sqlchemy.SUM("gnic_count", gNicQ.Field("gnic_count")),
|
||||
sqlchemy.SUM("hnic_count", hNicQ.Field("hnic_count")),
|
||||
sqlchemy.SUM("rev_count", revQ.Field("rnic_count"))).
|
||||
LeftJoin(gNicSQ, sqlchemy.Equals(gNicSQ.Field("network_id"), networks.Field("id"))).
|
||||
LeftJoin(hNicSQ, sqlchemy.Equals(hNicSQ.Field("network_id"), networks.Field("id"))).
|
||||
LeftJoin(revSQ, sqlchemy.Equals(revSQ.Field("network_id"), networks.Field("id"))).
|
||||
GroupBy(networks.Field("wire_id")).SubQuery()
|
||||
sqlchemy.SUM("rev_count", revQ.Field("rnic_count")))
|
||||
netQ = netQ.LeftJoin(gNicSQ, sqlchemy.Equals(gNicSQ.Field("network_id"), networks.Field("id")))
|
||||
netQ = netQ.LeftJoin(hNicSQ, sqlchemy.Equals(hNicSQ.Field("network_id"), networks.Field("id")))
|
||||
netQ = netQ.LeftJoin(revSQ, sqlchemy.Equals(revSQ.Field("network_id"), networks.Field("id")))
|
||||
netQ = netQ.GroupBy(networks.Field("wire_id"))
|
||||
netSQ := netQ.SubQuery()
|
||||
|
||||
wires := WireManager.Query().SubQuery()
|
||||
q := wires.Query(
|
||||
sqlchemy.COUNT("id").Label("wires_count"),
|
||||
sqlchemy.SUM("net_count", netQ.Field("net_count")),
|
||||
sqlchemy.SUM("guest_nic_count", netQ.Field("gnic_count")),
|
||||
sqlchemy.SUM("host_nic_count", netQ.Field("hnic_count")),
|
||||
sqlchemy.SUM("reserved_count", netQ.Field("rev_count")),
|
||||
).
|
||||
LeftJoin(netQ, sqlchemy.Equals(wires.Field("id"), netQ.Field("wire_id")))
|
||||
hostwires := HostwireManager.Query().SubQuery()
|
||||
sq := hostwires.Query(hostwires.Field("wire_id")).
|
||||
Join(hosts, sqlchemy.AND(
|
||||
sqlchemy.Equals(hosts.Field("id"), hostwires.Field("host_id")),
|
||||
sqlchemy.IsFalse(hosts.Field("deleted")),
|
||||
sqlchemy.IsTrue(hosts.Field("enabled"))))
|
||||
sq = AttachUsageQuery(sq, hosts, hosts.Field("id"), hostTypes, rangeObj)
|
||||
sqlchemy.SUM("net_count", netSQ.Field("net_count")),
|
||||
sqlchemy.SUM("guest_nic_count", netSQ.Field("gnic_count")),
|
||||
sqlchemy.SUM("host_nic_count", netSQ.Field("hnic_count")),
|
||||
sqlchemy.SUM("reserved_count", netSQ.Field("rev_count")),
|
||||
)
|
||||
q = q.LeftJoin(netSQ, sqlchemy.Equals(wires.Field("id"), netSQ.Field("wire_id")))
|
||||
|
||||
if rangeObj != nil || len(hostTypes) > 0 {
|
||||
hostwires := HostwireManager.Query().SubQuery()
|
||||
sq := hostwires.Query(hostwires.Field("wire_id"))
|
||||
sq = sq.Join(hosts, sqlchemy.Equals(hosts.Field("id"), hostwires.Field("host_id")))
|
||||
sq = sq.Filter(sqlchemy.IsTrue(hosts.Field("enabled")))
|
||||
sq = AttachUsageQuery(sq, hosts, hostTypes, nil, nil, rangeObj)
|
||||
q = q.Filter(sqlchemy.In(wires.Field("id"), sq.Distinct()))
|
||||
}
|
||||
|
||||
if len(providers) > 0 {
|
||||
vpcs := VpcManager.Query().SubQuery()
|
||||
cloudproviders := CloudproviderManager.Query().SubQuery()
|
||||
subq := vpcs.Query(vpcs.Field("id"))
|
||||
subq = subq.Join(cloudproviders, sqlchemy.Equals(vpcs.Field("manager_id"), cloudproviders.Field("id")))
|
||||
subq = subq.Filter(sqlchemy.In(cloudproviders.Field("provider"), providers))
|
||||
q = q.Filter(sqlchemy.In(wires.Field("vpc_id"), subq.SubQuery()))
|
||||
}
|
||||
|
||||
q = q.Filter(sqlchemy.In(wires.Field("id"), sq.Distinct()))
|
||||
return q
|
||||
}
|
||||
|
||||
@@ -348,9 +355,9 @@ type WiresCountStat struct {
|
||||
ReservedCount int
|
||||
}
|
||||
|
||||
func (manager *SWireManager) TotalCount(rangeObj db.IStandaloneModel, hostTypes []string) WiresCountStat {
|
||||
func (manager *SWireManager) TotalCount(rangeObj db.IStandaloneModel, hostTypes []string, providers []string) WiresCountStat {
|
||||
stat := WiresCountStat{}
|
||||
err := manager.totalCountQ(rangeObj, hostTypes).First(&stat)
|
||||
err := manager.totalCountQ(rangeObj, hostTypes, providers).First(&stat)
|
||||
if err != nil {
|
||||
log.Errorf("Wire total count: %v", err)
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ type ComputeOptions struct {
|
||||
PendingDeleteExpireSeconds int `default:"259200" help:"How long a pending delete VM/disks cleaned automatically, default 3 days"`
|
||||
PendingDeleteMaxCleanBatchSize int `default:"50" help:"How many pending delete servers can be clean in a batch"`
|
||||
|
||||
PrepaidExpireCheckSeconds int `default:"600" help:"How long to wait to scan expired prepaid VM or disks, default is 10 minutes"`
|
||||
ExpiredPrepaidMaxCleanBatchSize int `default:"50" help:"How many expired prepaid servers can be deleted in a batch"`
|
||||
|
||||
LoadbalancerPendingDeleteCheckInterval int `default:"3600" help:"Interval between checks of pending deleted loadbalancer objects, defaults to 1h"`
|
||||
|
||||
ImageCacheStoragePolicy string `default:"least_used" choices:"best_fit|least_used" help:"Policy to choose storage for image cache, best_fit or least_used"`
|
||||
|
||||
@@ -59,6 +59,8 @@ func StartService() {
|
||||
cron.AddJob1("CleanPendingDeleteServers", time.Duration(options.Options.PendingDeleteCheckSeconds)*time.Second, models.GuestManager.CleanPendingDeleteServers)
|
||||
cron.AddJob1("CleanPendingDeleteDisks", time.Duration(options.Options.PendingDeleteCheckSeconds)*time.Second, models.DiskManager.CleanPendingDeleteDisks)
|
||||
cron.AddJob1("CleanPendingDeleteLoadbalancers", time.Duration(options.Options.LoadbalancerPendingDeleteCheckInterval)*time.Second, models.LoadbalancerAgentManager.CleanPendingDeleteLoadbalancers)
|
||||
cron.AddJob1("CleanPendingDeleteServers", time.Duration(options.Options.PrepaidExpireCheckSeconds)*time.Second, models.GuestManager.DeleteExpiredPrepaidServers)
|
||||
|
||||
cron.AddJob2("AutoDiskSnapshot", options.Options.AutoSnapshotDay, options.Options.AutoSnapshotHour, 0, 0, models.DiskManager.AutoDiskSnapshot, false)
|
||||
cron.AddJob2("SyncSkus", options.Options.SyncSkusDay, options.Options.SyncSkusHour, 0, 0, skus.SyncSkus, true)
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package skus // import "yunion.io/x/onecloud/pkg/compute/skus"
|
||||
@@ -306,7 +306,12 @@ func (self *SkusZoneList) SyncToLocalDB() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func SyncSkus(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
func SyncSkus(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
|
||||
if isStart {
|
||||
if models.ServerSkuManager.GetSkuCountByProvider("") > 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
skus := SkusZoneList{}
|
||||
if e := skus.Refresh(nil); e != nil {
|
||||
log.Errorf("SyncSkus refresh failed, %s", e.Error())
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package specs // import "yunion.io/x/onecloud/pkg/compute/specs"
|
||||
@@ -84,10 +84,18 @@ func (self *CloudAccountSyncInfoTask) OnCloudaccountSyncComplete(ctx context.Con
|
||||
account.SetStatus(self.UserCred, models.CLOUD_PROVIDER_CONNECTED, "")
|
||||
}
|
||||
|
||||
// sync skus
|
||||
if err := skus.SyncSkusByProviderIds([]string{cloudprovider.Provider}); err != nil {
|
||||
self.SetStageFailed(ctx, err.Error())
|
||||
if models.ServerSkuManager.GetSkuCountByProvider(cloudprovider.Provider) == 0 {
|
||||
// sync skus
|
||||
self.SetStage("OnSyncServerSkuComplete", nil)
|
||||
taskman.LocalTaskRun(self, func() (jsonutils.JSONObject, error) {
|
||||
err := skus.SyncSkusByProviderIds([]string{cloudprovider.Provider})
|
||||
return nil, err
|
||||
})
|
||||
}
|
||||
}
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *CloudAccountSyncInfoTask) OnSyncServerSkuComplete(ctx context.Context, items []db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ func (self *GuestBatchCreateTask) SaveScheduleResult(ctx context.Context, obj IS
|
||||
log.Errorf("GetPendingUsage fail %s", err)
|
||||
}
|
||||
if len(guest.HostId) == 0 {
|
||||
guest.SetHostId(hostId)
|
||||
guest.OnScheduleToHost(ctx, self.UserCred, hostId)
|
||||
}
|
||||
|
||||
quotaCpuMem := models.SQuota{Cpu: int(guest.VcpuCount), Memory: guest.VmemSize}
|
||||
@@ -56,6 +56,20 @@ func (self *GuestBatchCreateTask) SaveScheduleResult(ctx context.Context, obj IS
|
||||
|
||||
host := guest.GetHost()
|
||||
|
||||
if host.IsPrepaidRecycle() {
|
||||
params, err := host.SetGuestCreateNetworkAndDiskParams(ctx, self.UserCred, self.Params)
|
||||
if err != nil {
|
||||
log.Errorf("host.SetGuestCreateNetworkAndDiskParams fail %s", err)
|
||||
guest.SetStatus(self.UserCred, models.VM_CREATE_FAILED, err.Error())
|
||||
self.SetStageFailed(ctx, err.Error())
|
||||
db.OpsLog.LogEvent(guest, db.ACT_ALLOCATE_FAIL, err, self.UserCred)
|
||||
notifyclient.NotifySystemError(guest.Id, guest.Name, models.VM_CREATE_FAILED, err.Error())
|
||||
return
|
||||
}
|
||||
self.Params = params
|
||||
self.SaveParams(params)
|
||||
}
|
||||
|
||||
err = guest.CreateNetworksOnHost(ctx, self.UserCred, host, self.Params, &pendingUsage)
|
||||
self.SetPendingUsage(&pendingUsage)
|
||||
|
||||
@@ -69,7 +83,7 @@ func (self *GuestBatchCreateTask) SaveScheduleResult(ctx context.Context, obj IS
|
||||
}
|
||||
|
||||
guest.GetDriver().PrepareDiskRaidConfig(host, self.Params)
|
||||
err = guest.CreateDisksOnHost(ctx, self.UserCred, host, self.Params, &pendingUsage)
|
||||
err = guest.CreateDisksOnHost(ctx, self.UserCred, host, self.Params, &pendingUsage, true)
|
||||
self.SetPendingUsage(&pendingUsage)
|
||||
|
||||
if err != nil {
|
||||
@@ -95,13 +109,38 @@ func (self *GuestBatchCreateTask) SaveScheduleResult(ctx context.Context, obj IS
|
||||
|
||||
guest.JoinGroups(self.UserCred, self.Params)
|
||||
|
||||
if guest.IsPrepaidRecycle() {
|
||||
err := host.RebuildRecycledGuest(ctx, self.UserCred, guest)
|
||||
if err != nil {
|
||||
log.Errorf("start guest create task fail %s", err)
|
||||
guest.SetStatus(self.UserCred, models.VM_CREATE_FAILED, err.Error())
|
||||
self.SetStageFailed(ctx, err.Error())
|
||||
db.OpsLog.LogEvent(guest, db.ACT_ALLOCATE_FAIL, err, self.UserCred)
|
||||
notifyclient.NotifySystemError(guest.Id, guest.Name, models.VM_CREATE_FAILED, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
autoStart := jsonutils.QueryBoolean(self.Params, "auto_start", false)
|
||||
resetPassword := jsonutils.QueryBoolean(self.Params, "reset_password", true)
|
||||
passwd, _ := self.Params.GetString("password")
|
||||
err = guest.StartRebuildRootTask(ctx, self.UserCred, "", false, autoStart, passwd, resetPassword, true)
|
||||
if err != nil {
|
||||
log.Errorf("start guest create task fail %s", err)
|
||||
guest.SetStatus(self.UserCred, models.VM_CREATE_FAILED, err.Error())
|
||||
self.SetStageFailed(ctx, err.Error())
|
||||
db.OpsLog.LogEvent(guest, db.ACT_ALLOCATE_FAIL, err, self.UserCred)
|
||||
notifyclient.NotifySystemError(guest.Id, guest.Name, models.VM_CREATE_FAILED, err.Error())
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
err = guest.StartGuestCreateTask(ctx, self.UserCred, self.Params, nil, self.GetId())
|
||||
if err != nil {
|
||||
log.Errorf("start guest create task fail %s", err)
|
||||
guest.SetStatus(self.UserCred, models.VM_CREATE_FAILED, err.Error())
|
||||
self.SetStageFailed(ctx, err.Error())
|
||||
db.OpsLog.LogEvent(guest, db.ACT_ALLOCATE_FAIL, err, self.UserCred)
|
||||
notifyclient.NotifySystemError(guest.Id, guest.Name, models.VM_DEVICE_FAILED, err.Error())
|
||||
notifyclient.NotifySystemError(guest.Id, guest.Name, models.VM_CREATE_FAILED, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -155,7 +156,16 @@ func (self *GuestDeleteTask) OnGuestDetachDisksCompleteFailed(ctx context.Contex
|
||||
func (self *GuestDeleteTask) DoDeleteGuest(ctx context.Context, guest *models.SGuest) {
|
||||
models.IsolatedDeviceManager.ReleaseDevicesOfGuest(guest, self.UserCred)
|
||||
host := guest.GetHost()
|
||||
if (host == nil || !host.Enabled) && jsonutils.QueryBoolean(self.Params, "purge", false) {
|
||||
if guest.IsPrepaidRecycle() {
|
||||
err := host.BorrowIpAddrsFromGuest(ctx, self.UserCred, guest)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("host.BorrowIpAddrsFromGuest fail %s", err)
|
||||
log.Errorf(msg)
|
||||
self.OnGuestDeleteFailed(ctx, guest, jsonutils.NewString(msg))
|
||||
return
|
||||
}
|
||||
self.OnGuestDeleteComplete(ctx, guest, nil)
|
||||
} else if (host == nil || !host.Enabled) && jsonutils.QueryBoolean(self.Params, "purge", false) {
|
||||
self.OnGuestDeleteComplete(ctx, guest, nil)
|
||||
} else {
|
||||
self.SetStage("on_guest_delete_complete", nil)
|
||||
|
||||
@@ -301,7 +301,7 @@ func (self *GuestMigrateTask) setGuest(ctx context.Context, guest *models.SGuest
|
||||
}
|
||||
oldHost := guest.GetHost()
|
||||
oldHost.ClearSchedDescCache()
|
||||
err := guest.SetHostId(targetHostId)
|
||||
err := guest.OnScheduleToHost(ctx, self.UserCred, targetHostId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -71,6 +71,48 @@ func (self *GuestRebuildRootTask) StartRebuildRootDisk(ctx context.Context, gues
|
||||
}
|
||||
|
||||
func (self *GuestRebuildRootTask) OnRebuildRootDiskComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
allDisks := jsonutils.QueryBoolean(self.Params, "all_disks", false)
|
||||
if allDisks {
|
||||
guestdisks := guest.GetDisks()
|
||||
for i := 1; i < len(guestdisks); i += 1 {
|
||||
disk := guestdisks[i].GetDisk()
|
||||
if disk != nil {
|
||||
disk.SetStatus(self.UserCred, models.DISK_INIT, "rebuild data disks")
|
||||
}
|
||||
}
|
||||
self.SetStage("OnRebuildingDataDisksComplete", nil)
|
||||
self.OnRebuildingDataDisksComplete(ctx, guest, data)
|
||||
} else {
|
||||
self.OnRebuildAllDisksComplete(ctx, guest, data)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *GuestRebuildRootTask) OnRebuildingDataDisksComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
diskReady := true
|
||||
guestdisks := guest.GetDisks()
|
||||
if len(guestdisks) > 0 {
|
||||
guest.SetStatus(self.UserCred, models.VM_REBUILD_ROOT, "rebuild data disks")
|
||||
}
|
||||
for i := 1; i < len(guestdisks); i += 1 {
|
||||
disk := guestdisks[i].GetDisk()
|
||||
if disk.Status == models.DISK_INIT {
|
||||
diskReady = false
|
||||
disk.StartDiskCreateTask(ctx, self.UserCred, true, "", self.GetTaskId())
|
||||
}
|
||||
}
|
||||
if diskReady {
|
||||
self.OnRebuildAllDisksComplete(ctx, guest, data)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *GuestRebuildRootTask) OnRebuildingDataDisksCompleteFailed(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
db.OpsLog.LogEvent(guest, db.ACT_REBUILD_ROOT_FAIL, data, self.UserCred)
|
||||
guest.SetStatus(self.UserCred, models.VM_REBUILD_ROOT_FAIL, "OnRebuildingDataDisksCompleteFailed")
|
||||
logclient.AddActionLog(guest, logclient.ACT_VM_REBUILD, data, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, data.String())
|
||||
}
|
||||
|
||||
func (self *GuestRebuildRootTask) OnRebuildAllDisksComplete(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
imgId, _ := self.Params.GetString("image_id")
|
||||
imginfo, err := models.CachedimageManager.GetImageById(ctx, self.UserCred, imgId, false)
|
||||
if err != nil {
|
||||
@@ -109,7 +151,7 @@ func (self *GuestRebuildRootTask) OnRebuildRootDiskComplete(ctx context.Context,
|
||||
|
||||
func (self *GuestRebuildRootTask) OnRebuildRootDiskCompleteFailed(ctx context.Context, guest *models.SGuest, data jsonutils.JSONObject) {
|
||||
db.OpsLog.LogEvent(guest, db.ACT_REBUILD_ROOT_FAIL, data, self.UserCred)
|
||||
guest.SetStatus(self.UserCred, models.VM_REBUILD_ROOT_FAIL, "")
|
||||
guest.SetStatus(self.UserCred, models.VM_REBUILD_ROOT_FAIL, "OnRebuildRootDiskCompleteFailed")
|
||||
logclient.AddActionLog(guest, logclient.ACT_VM_REBUILD, data, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, data.String())
|
||||
}
|
||||
@@ -162,7 +204,6 @@ func (self *KVMGuestRebuildRootTask) OnRebuildRootDiskCompleteFailed(ctx context
|
||||
|
||||
func (self *KVMGuestRebuildRootTask) OnGuestDeployComplete(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
|
||||
self.SetStageComplete(ctx, nil)
|
||||
logclient.AddActionLog(guest, logclient.ACT_VM_REBUILD, nil, self.UserCred, true)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"fmt"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
type GuestRenewTask struct {
|
||||
SGuestBaseTask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(GuestRenewTask{})
|
||||
}
|
||||
|
||||
func (self *GuestRenewTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
guest := obj.(*models.SGuest)
|
||||
|
||||
durationStr, _ := self.GetParams().GetString("duration")
|
||||
bc, _ := billing.ParseBillingCycle(durationStr)
|
||||
|
||||
exp, err := guest.GetDriver().RequestRenewInstance(guest, bc)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("RequestRenewInstance failed %s", err)
|
||||
log.Errorf(msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
err = guest.SaveRenewInfo(self.UserCred, &bc, &exp)
|
||||
if err != nil {
|
||||
msg := fmt.Sprintf("SaveRenewInfo fail %s", err)
|
||||
log.Errorf(msg)
|
||||
self.SetStageFailed(ctx, msg)
|
||||
return
|
||||
}
|
||||
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -34,7 +34,7 @@ type IScheduleTask interface {
|
||||
GetUserCred() mcclient.TokenCredential
|
||||
GetSchedParams() *jsonutils.JSONDict
|
||||
GetPendingUsage(quota quotas.IQuota) error
|
||||
SetStage(stageName string, data *jsonutils.JSONDict)
|
||||
SetStage(stageName string, data *jsonutils.JSONDict) error
|
||||
SetStageFailed(ctx context.Context, reason string)
|
||||
|
||||
OnStartSchedule(obj IScheduleModel)
|
||||
@@ -212,8 +212,8 @@ func onScheduleSucc(
|
||||
obj IScheduleModel,
|
||||
hostId string,
|
||||
) {
|
||||
lockman.LockObject(ctx, obj)
|
||||
defer lockman.ReleaseObject(ctx, obj)
|
||||
lockman.LockRawObject(ctx, models.HostManager.KeywordPlural(), hostId)
|
||||
defer lockman.ReleaseRawObject(ctx, models.HostManager.KeywordPlural(), hostId)
|
||||
|
||||
task.SaveScheduleResult(ctx, obj, hostId)
|
||||
models.HostManager.ClearSchedDescCache(hostId)
|
||||
|
||||
+225
-106
@@ -48,7 +48,7 @@ func (u Usage) Include(nus ...Usage) Usage {
|
||||
return u
|
||||
}
|
||||
|
||||
type objUsageFunc func(mcclient.TokenCredential, db.IStandaloneModel, []string) (Usage, error)
|
||||
type objUsageFunc func(mcclient.TokenCredential, db.IStandaloneModel, []string, []string) (Usage, error)
|
||||
|
||||
func getRangeObjId(ctx context.Context) (string, error) {
|
||||
params := appctx.AppContextParams(ctx)
|
||||
@@ -81,7 +81,7 @@ func rangeObjHandler(
|
||||
httperrors.NotFoundError(w, err.Error())
|
||||
return
|
||||
}
|
||||
projectName, _ := getQuery(r).GetString("project")
|
||||
projectName := json.GetAnyString(getQuery(r), []string{"project", "tenant"})
|
||||
if projectName != "" {
|
||||
userCred, err = generateProjectUserCred(ctx, userCred, projectName)
|
||||
if err != nil {
|
||||
@@ -89,7 +89,11 @@ func rangeObjHandler(
|
||||
return
|
||||
}
|
||||
}
|
||||
usage, err := reporter(userCred, obj, getHostTypes(r))
|
||||
query := getQuery(r)
|
||||
hostTypes := json.GetQueryStringArray(query, "host_type")
|
||||
// resourceTypes := json.GetQueryStringArray(query, "resource_type")
|
||||
providers := json.GetQueryStringArray(query, "provider")
|
||||
usage, err := reporter(userCred, obj, hostTypes, providers)
|
||||
if err != nil {
|
||||
httperrors.GeneralServerError(w, err)
|
||||
return
|
||||
@@ -124,13 +128,14 @@ func addHandler(prefix, rangeObjKey string, hf appsrv.FilterHandler, app *appsrv
|
||||
func AddUsageHandler(prefix string, app *appsrv.Application) {
|
||||
prefix = fmt.Sprintf("%s/usages", prefix)
|
||||
for key, f := range map[string]appsrv.FilterHandler{
|
||||
"": rangeObjHandler(nil, ReportGeneralUsage),
|
||||
"zone": rangeObjHandler(models.ZoneManager, ReportZoneUsage),
|
||||
"wire": rangeObjHandler(models.WireManager, ReportWireUsage),
|
||||
"schedtag": rangeObjHandler(models.SchedtagManager, ReportSchedtagUsage),
|
||||
"host": rangeObjHandler(models.HostManager, ReportHostUsage),
|
||||
"vcenter": rangeObjHandler(models.VCenterManager, ReportVCenterUsage),
|
||||
"cloudregion": rangeObjHandler(models.CloudregionManager, ReportCloudRegionUsage),
|
||||
"": rangeObjHandler(nil, ReportGeneralUsage),
|
||||
"zone": rangeObjHandler(models.ZoneManager, ReportZoneUsage),
|
||||
"wire": rangeObjHandler(models.WireManager, ReportWireUsage),
|
||||
"schedtag": rangeObjHandler(models.SchedtagManager, ReportSchedtagUsage),
|
||||
"host": rangeObjHandler(models.HostManager, ReportHostUsage),
|
||||
"cloudaccount": rangeObjHandler(models.CloudaccountManager, ReportCloudAccountUsage),
|
||||
"cloudprovider": rangeObjHandler(models.CloudproviderManager, ReportCloudProviderUsage),
|
||||
"cloudregion": rangeObjHandler(models.CloudregionManager, ReportCloudRegionUsage),
|
||||
} {
|
||||
addHandler(prefix, key, f, app)
|
||||
}
|
||||
@@ -151,47 +156,45 @@ func getQuery(r *http.Request) json.JSONObject {
|
||||
return query
|
||||
}
|
||||
|
||||
func getHostTypes(r *http.Request) []string {
|
||||
types := make([]string, 0)
|
||||
t, _ := getQuery(r).GetString("host_type")
|
||||
if len(t) != 0 {
|
||||
types = append(types, t)
|
||||
}
|
||||
return types
|
||||
func ReportHostUsage(userCred mcclient.TokenCredential, host db.IStandaloneModel, hostTypes []string, providers []string) (Usage, error) {
|
||||
return ReportGeneralUsage(userCred, host, hostTypes, providers)
|
||||
}
|
||||
|
||||
func ReportHostUsage(userCred mcclient.TokenCredential, host db.IStandaloneModel, hostTypes []string) (Usage, error) {
|
||||
return ReportGeneralUsage(userCred, host, hostTypes)
|
||||
func ReportWireUsage(userCred mcclient.TokenCredential, wire db.IStandaloneModel, hostTypes []string, providers []string) (Usage, error) {
|
||||
return ReportGeneralUsage(userCred, wire, hostTypes, providers)
|
||||
}
|
||||
|
||||
func ReportWireUsage(userCred mcclient.TokenCredential, wire db.IStandaloneModel, hostTypes []string) (Usage, error) {
|
||||
return ReportGeneralUsage(userCred, wire, hostTypes)
|
||||
func ReportCloudAccountUsage(userCred mcclient.TokenCredential, account db.IStandaloneModel, hostTypes []string, providers []string) (Usage, error) {
|
||||
return ReportGeneralUsage(userCred, account, hostTypes, providers)
|
||||
}
|
||||
|
||||
func ReportVCenterUsage(userCred mcclient.TokenCredential, vcenter db.IStandaloneModel, hostTypes []string) (Usage, error) {
|
||||
return ReportGeneralUsage(userCred, vcenter, hostTypes)
|
||||
func ReportCloudProviderUsage(userCred mcclient.TokenCredential, provider db.IStandaloneModel, hostTypes []string, providers []string) (Usage, error) {
|
||||
return ReportGeneralUsage(userCred, provider, hostTypes, providers)
|
||||
}
|
||||
|
||||
func ReportSchedtagUsage(userCred mcclient.TokenCredential, schedtag db.IStandaloneModel, hostTypes []string) (Usage, error) {
|
||||
return ReportGeneralUsage(userCred, schedtag, hostTypes)
|
||||
func ReportSchedtagUsage(userCred mcclient.TokenCredential, schedtag db.IStandaloneModel, hostTypes []string, providers []string) (Usage, error) {
|
||||
return ReportGeneralUsage(userCred, schedtag, hostTypes, providers)
|
||||
}
|
||||
|
||||
func ReportZoneUsage(userCred mcclient.TokenCredential, zone db.IStandaloneModel, hostTypes []string) (Usage, error) {
|
||||
return ReportGeneralUsage(userCred, zone, hostTypes)
|
||||
func ReportZoneUsage(userCred mcclient.TokenCredential, zone db.IStandaloneModel, hostTypes []string, providers []string) (Usage, error) {
|
||||
return ReportGeneralUsage(userCred, zone, hostTypes, providers)
|
||||
}
|
||||
|
||||
func ReportCloudRegionUsage(userCred mcclient.TokenCredential, cloudRegion db.IStandaloneModel, hostTypes []string) (Usage, error) {
|
||||
return ReportGeneralUsage(userCred, cloudRegion, hostTypes)
|
||||
func ReportCloudRegionUsage(userCred mcclient.TokenCredential, cloudRegion db.IStandaloneModel, hostTypes []string, providers []string) (Usage, error) {
|
||||
return ReportGeneralUsage(userCred, cloudRegion, hostTypes, providers)
|
||||
}
|
||||
|
||||
//func ReportGuestUsage()
|
||||
func getAdminGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string, providers []string) (count Usage, err error) {
|
||||
count = RegionUsage(providers)
|
||||
zone := ZoneUsage(providers)
|
||||
count.Include(zone)
|
||||
vpc := VpcUsage(providers)
|
||||
count.Include(vpc)
|
||||
|
||||
func getAdminGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) (count Usage, err error) {
|
||||
count = ZoneUsage()
|
||||
var pmemTotal float64
|
||||
var pcpuTotal float64
|
||||
|
||||
hostEnabledUsage := HostEnabledUsage(userCred, rangeObj, hostTypes)
|
||||
hostEnabledUsage := HostEnabledUsage("", userCred, rangeObj, hostTypes, []string{models.HostResourceTypeShared}, providers)
|
||||
pmemTotal = float64(hostEnabledUsage.Get("enabled_hosts.memory").(int64))
|
||||
pcpuTotal = float64(hostEnabledUsage.Get("enabled_hosts.cpu").(int64))
|
||||
if rangeObj != nil && rangeObj.Keyword() == "host" {
|
||||
@@ -203,10 +206,12 @@ func getAdminGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStanda
|
||||
count.Add("memory.virtual", host.GetVirtualMemorySize())
|
||||
count.Add("cpu.virtual", host.GetVirtualCPUCount())
|
||||
}
|
||||
guestRunningUsage := GuestRunningUsage("all.running_servers", nil, rangeObj, hostTypes)
|
||||
|
||||
guestRunningUsage := GuestRunningUsage("all.running_servers", nil, rangeObj, hostTypes, []string{models.HostResourceTypeShared}, providers)
|
||||
runningMem := guestRunningUsage.Get("all.running_servers.memory").(int)
|
||||
runningCpu := guestRunningUsage.Get("all.running_servers.cpu").(int)
|
||||
containerRunningUsage := containerUsage("all.containers", nil, rangeObj)
|
||||
|
||||
containerRunningUsage := containerUsage("all.containers", nil, rangeObj, hostTypes, nil, providers)
|
||||
containerRunningMem := containerRunningUsage.Get("all.containers.memory").(int)
|
||||
containerRunningCpu := containerRunningUsage.Get("all.containers.cpu").(int)
|
||||
runningMem += containerRunningMem
|
||||
@@ -222,50 +227,92 @@ func getAdminGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStanda
|
||||
count.Add("all.memory_commit_rate.running", runningMemCmtRate)
|
||||
count.Add("all.cpu_commit_rate.running", runningCpuCmtRate)
|
||||
|
||||
storageUsage := StorageUsage(rangeObj, hostTypes)
|
||||
storageCmtRate := 0.0
|
||||
disksSize := storageUsage.Get("all.disks").(int64)
|
||||
storageSize := storageUsage.Get("storages").(int64)
|
||||
if storageSize > 0 {
|
||||
storageCmtRate = utils.FloatRound(float64(disksSize)/float64(storageSize), 2)
|
||||
}
|
||||
count.Add("storages_commit_rate", storageCmtRate)
|
||||
storageUsage := StorageUsage("", rangeObj, hostTypes, []string{models.HostResourceTypeShared}, providers)
|
||||
|
||||
count.Include(
|
||||
HostAllUsage(userCred, rangeObj, hostTypes),
|
||||
HostAllUsage("", userCred, rangeObj, hostTypes, []string{models.HostResourceTypeShared}, providers),
|
||||
HostAllUsage("prepaid_pool", userCred, rangeObj, hostTypes, []string{models.HostResourceTypePrepaidRecycle}, providers),
|
||||
HostAllUsage("any_pool", userCred, rangeObj, hostTypes, nil, providers),
|
||||
|
||||
hostEnabledUsage,
|
||||
BaremetalUsage(userCred, rangeObj, hostTypes),
|
||||
HostEnabledUsage("prepaid_pool", userCred, rangeObj, hostTypes, []string{models.HostResourceTypePrepaidRecycle}, providers),
|
||||
HostEnabledUsage("any_pool", userCred, rangeObj, hostTypes, nil, providers),
|
||||
|
||||
BaremetalUsage(userCred, rangeObj, hostTypes, providers),
|
||||
|
||||
storageUsage,
|
||||
GuestNormalUsage("all.servers", nil, rangeObj, hostTypes),
|
||||
GuestPendingDeleteUsage("all.pending_delete_servers", nil, rangeObj, hostTypes),
|
||||
GuestReadyUsage("all.ready_servers", nil, rangeObj, hostTypes),
|
||||
StorageUsage("prepaid_pool", rangeObj, hostTypes, []string{models.HostResourceTypePrepaidRecycle}, providers),
|
||||
StorageUsage("any_pool", rangeObj, hostTypes, nil, providers),
|
||||
|
||||
GuestNormalUsage("all.servers", nil, rangeObj, hostTypes, []string{models.HostResourceTypeShared}, providers),
|
||||
GuestNormalUsage("all.servers.prepaid_pool", nil, rangeObj, hostTypes, []string{models.HostResourceTypePrepaidRecycle}, providers),
|
||||
GuestNormalUsage("all.servers.any_pool", nil, rangeObj, hostTypes, nil, providers),
|
||||
|
||||
GuestPendingDeleteUsage("all.pending_delete_servers", nil, rangeObj, hostTypes, []string{models.HostResourceTypeShared}, providers),
|
||||
GuestPendingDeleteUsage("all.pending_delete_servers.prepaid_pool", nil, rangeObj, hostTypes, []string{models.HostResourceTypePrepaidRecycle}, providers),
|
||||
GuestPendingDeleteUsage("all.pending_delete_servers.any_pool", nil, rangeObj, hostTypes, nil, providers),
|
||||
|
||||
GuestReadyUsage("all.ready_servers", nil, rangeObj, hostTypes, []string{models.HostResourceTypeShared}, providers),
|
||||
GuestReadyUsage("all.ready_servers.prepaid_pool", nil, rangeObj, hostTypes, []string{models.HostResourceTypePrepaidRecycle}, providers),
|
||||
GuestReadyUsage("all.ready_servers.any_pool", nil, rangeObj, hostTypes, nil, providers),
|
||||
|
||||
guestRunningUsage,
|
||||
GuestRunningUsage("all.running_servers.prepaid_pool", nil, rangeObj, hostTypes, []string{models.HostResourceTypePrepaidRecycle}, providers),
|
||||
GuestRunningUsage("all.running_servers.any_pool", nil, rangeObj, hostTypes, nil, providers),
|
||||
|
||||
containerRunningUsage,
|
||||
IsolatedDeviceUsage(rangeObj, hostTypes),
|
||||
WireUsage(rangeObj, hostTypes),
|
||||
EipUsage(rangeObj, hostTypes),
|
||||
|
||||
IsolatedDeviceUsage("", rangeObj, hostTypes, []string{models.HostResourceTypeShared}, providers),
|
||||
IsolatedDeviceUsage("prepaid_pool", rangeObj, hostTypes, []string{models.HostResourceTypePrepaidRecycle}, providers),
|
||||
IsolatedDeviceUsage("any_pool", rangeObj, hostTypes, nil, providers),
|
||||
|
||||
WireUsage(rangeObj, hostTypes, providers),
|
||||
|
||||
EipUsage("", rangeObj, providers),
|
||||
|
||||
SnapshotUsage("", rangeObj, providers),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func getCommonGeneralUsage(cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) (count Usage, err error) {
|
||||
guestNormalUsage := GuestNormalUsage("servers", cred, rangeObj, hostTypes)
|
||||
guestRunningUsage := GuestRunningUsage("running_servers", cred, rangeObj, hostTypes)
|
||||
guestPendingDeleteUsage := GuestPendingDeleteUsage("pending_delete_servers", cred, rangeObj, hostTypes)
|
||||
guestReadyUsage := GuestReadyUsage("ready_servers", cred, rangeObj, hostTypes)
|
||||
containerUsage := containerUsage("containers", cred, rangeObj)
|
||||
func getCommonGeneralUsage(cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string, providers []string) (count Usage, err error) {
|
||||
guestNormalUsage := GuestNormalUsage("servers", cred, rangeObj, hostTypes, []string{models.HostResourceTypeShared}, providers)
|
||||
|
||||
containerUsage := containerUsage("containers", cred, rangeObj, hostTypes, nil, providers)
|
||||
|
||||
eipUsage := EipUsage(cred.GetProjectId(), rangeObj, providers)
|
||||
|
||||
snapshotUsage := SnapshotUsage(cred.GetProjectId(), rangeObj, providers)
|
||||
|
||||
count = guestNormalUsage.Include(
|
||||
guestRunningUsage,
|
||||
guestPendingDeleteUsage,
|
||||
guestReadyUsage,
|
||||
GuestNormalUsage("servers.prepaid_pool", cred, rangeObj, hostTypes, []string{models.HostResourceTypePrepaidRecycle}, providers),
|
||||
GuestNormalUsage("servers.any_pool", cred, rangeObj, hostTypes, nil, providers),
|
||||
|
||||
GuestRunningUsage("running_servers", cred, rangeObj, hostTypes, []string{models.HostResourceTypeShared}, providers),
|
||||
GuestRunningUsage("running_servers.prepaid_pool", cred, rangeObj, hostTypes, []string{models.HostResourceTypePrepaidRecycle}, providers),
|
||||
GuestRunningUsage("running_servers.any_pool", cred, rangeObj, hostTypes, nil, providers),
|
||||
|
||||
GuestPendingDeleteUsage("pending_delete_servers", cred, rangeObj, hostTypes, []string{models.HostResourceTypeShared}, providers),
|
||||
GuestPendingDeleteUsage("pending_delete_servers.prepaid_pool", cred, rangeObj, hostTypes, []string{models.HostResourceTypePrepaidRecycle}, providers),
|
||||
GuestPendingDeleteUsage("pending_delete_servers.any_pool", cred, rangeObj, hostTypes, nil, providers),
|
||||
|
||||
GuestReadyUsage("ready_servers", cred, rangeObj, hostTypes, []string{models.HostResourceTypeShared}, providers),
|
||||
GuestReadyUsage("ready_servers.prepaid_pool", cred, rangeObj, hostTypes, []string{models.HostResourceTypePrepaidRecycle}, providers),
|
||||
GuestReadyUsage("ready_servers.any_pool", cred, rangeObj, hostTypes, nil, providers),
|
||||
|
||||
containerUsage,
|
||||
NetworkUsage(cred, rangeObj),
|
||||
|
||||
NetworkUsage(cred, providers, rangeObj),
|
||||
|
||||
eipUsage,
|
||||
|
||||
snapshotUsage,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
func ReportGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) (count Usage, err error) {
|
||||
func ReportGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string, providers []string) (count Usage, err error) {
|
||||
count = make(map[string]interface{})
|
||||
|
||||
isAdmin := false
|
||||
@@ -280,7 +327,7 @@ func ReportGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandalo
|
||||
}
|
||||
|
||||
if isAdmin {
|
||||
count, err = getAdminGeneralUsage(userCred, rangeObj, hostTypes)
|
||||
count, err = getAdminGeneralUsage(userCred, rangeObj, hostTypes, providers)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -303,7 +350,7 @@ func ReportGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandalo
|
||||
|
||||
if includeCommon {
|
||||
var commonUsage map[string]interface{}
|
||||
commonUsage, err = getCommonGeneralUsage(userCred, rangeObj, hostTypes)
|
||||
commonUsage, err = getCommonGeneralUsage(userCred, rangeObj, hostTypes, providers)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -312,29 +359,68 @@ func ReportGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandalo
|
||||
return
|
||||
}
|
||||
|
||||
func ZoneUsage() Usage {
|
||||
func RegionUsage(providers []string) Usage {
|
||||
q := models.CloudregionManager.Query()
|
||||
if len(providers) > 0 {
|
||||
q = q.In("provider", providers)
|
||||
}
|
||||
count := make(map[string]interface{})
|
||||
count["zones"] = models.ZoneManager.Count()
|
||||
count["regions"] = q.Count()
|
||||
return count
|
||||
}
|
||||
|
||||
func StorageUsage(rangeObj db.IStandaloneModel, hostTypes []string) Usage {
|
||||
func ZoneUsage(providers []string) Usage {
|
||||
regions := models.CloudregionManager.Query().SubQuery()
|
||||
subq := regions.Query(regions.Field("id"))
|
||||
if len(providers) > 0 {
|
||||
subq = subq.In("provider", providers)
|
||||
}
|
||||
q := models.ZoneManager.Query().In("cloudregion_id", subq.SubQuery())
|
||||
count := make(map[string]interface{})
|
||||
count["zones"] = q.Count()
|
||||
return count
|
||||
}
|
||||
|
||||
func VpcUsage(providers []string) Usage {
|
||||
regions := models.CloudregionManager.Query().SubQuery()
|
||||
subq := regions.Query(regions.Field("id"))
|
||||
if len(providers) > 0 {
|
||||
subq = subq.In("provider", providers)
|
||||
}
|
||||
q := models.VpcManager.Query().In("cloudregion_id", subq.SubQuery())
|
||||
count := make(map[string]interface{})
|
||||
count["vpcs"] = q.Count()
|
||||
return count
|
||||
}
|
||||
|
||||
func StorageUsage(prefix string, rangeObj db.IStandaloneModel, hostTypes []string, resourceTypes []string, providers []string) Usage {
|
||||
sPrefix := "storages"
|
||||
dPrefix := "all.disks"
|
||||
if len(prefix) > 0 {
|
||||
sPrefix = fmt.Sprintf("%s.%s", sPrefix, prefix)
|
||||
dPrefix = fmt.Sprintf("%s.%s", dPrefix, prefix)
|
||||
}
|
||||
count := make(map[string]interface{})
|
||||
result := models.StorageManager.TotalCapacity(rangeObj, hostTypes)
|
||||
result := models.StorageManager.TotalCapacity(rangeObj, hostTypes, resourceTypes, providers)
|
||||
count[sPrefix] = result.Capacity
|
||||
count[fmt.Sprintf("%s.virtual", sPrefix)] = result.CapacityVirtual
|
||||
count[dPrefix] = result.CapacityUsed
|
||||
count[fmt.Sprintf("%s.unready", dPrefix)] = result.CapacityUnread
|
||||
count[fmt.Sprintf("%s.unready", dPrefix)] = result.CapacityUnready
|
||||
count[fmt.Sprintf("%s.attached", dPrefix)] = result.AttachedCapacity
|
||||
count[fmt.Sprintf("%s.detached", dPrefix)] = result.DetachedCapacity
|
||||
|
||||
storageCmtRate := 0.0
|
||||
if result.Capacity > 0 {
|
||||
storageCmtRate = utils.FloatRound(float64(result.CapacityUsed)/float64(result.Capacity), 2)
|
||||
}
|
||||
count[fmt.Sprintf("%s.commit_rate", sPrefix)] = storageCmtRate
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
func WireUsage(rangeObj db.IStandaloneModel, hostTypes []string) Usage {
|
||||
func WireUsage(rangeObj db.IStandaloneModel, hostTypes []string, providers []string) Usage {
|
||||
count := make(map[string]interface{})
|
||||
result := models.WireManager.TotalCount(rangeObj, hostTypes)
|
||||
result := models.WireManager.TotalCount(rangeObj, hostTypes, providers)
|
||||
count["wires"] = result.WiresCount
|
||||
count["networks"] = result.NetCount
|
||||
count["all.nics.guest"] = result.GuestNicCount
|
||||
@@ -343,27 +429,36 @@ func WireUsage(rangeObj db.IStandaloneModel, hostTypes []string) Usage {
|
||||
return count
|
||||
}
|
||||
|
||||
func NetworkUsage(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel) Usage {
|
||||
func NetworkUsage(userCred mcclient.TokenCredential, providers []string, rangeObj db.IStandaloneModel) Usage {
|
||||
count := make(map[string]interface{})
|
||||
ret := models.NetworkManager.TotalPortCount(userCred, rangeObj)
|
||||
ret := models.NetworkManager.TotalPortCount(userCred, providers, rangeObj)
|
||||
count["ports"] = ret.Count
|
||||
count["ports_exit"] = ret.CountExt
|
||||
return count
|
||||
}
|
||||
|
||||
func HostAllUsage(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage {
|
||||
func HostAllUsage(pref string, userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel,
|
||||
hostTypes []string, resourceTypes []string, providers []string) Usage {
|
||||
prefix := "hosts"
|
||||
return hostUsage(userCred, prefix, rangeObj, hostTypes, tristate.None, tristate.None)
|
||||
if len(pref) > 0 {
|
||||
prefix = fmt.Sprintf("%s.%s", prefix, pref)
|
||||
}
|
||||
return hostUsage(userCred, prefix, rangeObj, hostTypes, resourceTypes, providers, tristate.None, tristate.None)
|
||||
}
|
||||
|
||||
func HostEnabledUsage(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage {
|
||||
func HostEnabledUsage(pref string, userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel,
|
||||
hostTypes []string, resourceTypes []string, providers []string) Usage {
|
||||
prefix := "enabled_hosts"
|
||||
return hostUsage(userCred, prefix, rangeObj, hostTypes, tristate.True, tristate.None)
|
||||
if len(pref) > 0 {
|
||||
prefix = fmt.Sprintf("%s.%s", prefix, pref)
|
||||
}
|
||||
return hostUsage(userCred, prefix, rangeObj, hostTypes, resourceTypes, providers, tristate.True, tristate.None)
|
||||
}
|
||||
|
||||
func BaremetalUsage(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage {
|
||||
func BaremetalUsage(userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel,
|
||||
hostTypes []string, providers []string) Usage {
|
||||
prefix := "baremetals"
|
||||
count := hostUsage(userCred, prefix, rangeObj, hostTypes, tristate.None, tristate.True)
|
||||
count := hostUsage(userCred, prefix, rangeObj, hostTypes, nil, providers, tristate.None, tristate.True)
|
||||
delete(count, fmt.Sprintf("%s.memory.virtual", prefix))
|
||||
delete(count, fmt.Sprintf("%s.cpu.virtual", prefix))
|
||||
return count
|
||||
@@ -372,11 +467,12 @@ func BaremetalUsage(userCred mcclient.TokenCredential, rangeObj db.IStandaloneMo
|
||||
func hostUsage(
|
||||
userCred mcclient.TokenCredential, prefix string,
|
||||
rangeObj db.IStandaloneModel, hostTypes []string,
|
||||
resourceTypes []string, providers []string,
|
||||
enabled, isBaremetal tristate.TriState,
|
||||
) Usage {
|
||||
count := make(map[string]interface{})
|
||||
|
||||
result := models.HostManager.TotalCount(userCred, rangeObj, "", "", hostTypes, enabled, isBaremetal)
|
||||
result := models.HostManager.TotalCount(userCred, rangeObj, "", "", hostTypes, resourceTypes, providers, enabled, isBaremetal)
|
||||
count[prefix] = result.Count
|
||||
count[fmt.Sprintf("%s.memory", prefix)] = result.Memory
|
||||
count[fmt.Sprintf("%s.cpu", prefix)] = result.CPU
|
||||
@@ -386,38 +482,35 @@ func hostUsage(
|
||||
return count
|
||||
}
|
||||
|
||||
func GuestNormalUsage(prefix string, cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage {
|
||||
return guestUsage(prefix, cred, rangeObj, hostTypes, nil, false)
|
||||
func GuestNormalUsage(prefix string, cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string, resourceTypes []string, providers []string) Usage {
|
||||
return guestUsage(prefix, cred, rangeObj, hostTypes, resourceTypes, providers, nil, false)
|
||||
}
|
||||
|
||||
func GuestPendingDeleteUsage(prefix string, cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage {
|
||||
return guestUsage(prefix, cred, rangeObj, hostTypes, nil, true)
|
||||
func GuestPendingDeleteUsage(prefix string, cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string, resourceTypes []string, providers []string) Usage {
|
||||
return guestUsage(prefix, cred, rangeObj, hostTypes, resourceTypes, providers, nil, true)
|
||||
}
|
||||
|
||||
func GuestRunningUsage(prefix string, cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage {
|
||||
return guestUsage(prefix, cred, rangeObj, hostTypes, []string{models.VM_RUNNING}, false)
|
||||
func GuestRunningUsage(prefix string, cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string, resourceTypes []string, providers []string) Usage {
|
||||
return guestUsage(prefix, cred, rangeObj, hostTypes, resourceTypes, providers, []string{models.VM_RUNNING}, false)
|
||||
}
|
||||
|
||||
func GuestReadyUsage(prefix string, cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string) Usage {
|
||||
return guestUsage(prefix, cred, rangeObj, hostTypes, []string{models.VM_READY}, false)
|
||||
func GuestReadyUsage(prefix string, cred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes []string, resourceTypes []string, providers []string) Usage {
|
||||
return guestUsage(prefix, cred, rangeObj, hostTypes, resourceTypes, providers, []string{models.VM_READY}, false)
|
||||
}
|
||||
|
||||
func guestHypervisorsUsage(
|
||||
prefix string,
|
||||
userCred mcclient.TokenCredential,
|
||||
rangeObj db.IStandaloneModel,
|
||||
hostTypes, status, hypervisors []string,
|
||||
hostTypes []string, resourceTypes []string, providers []string,
|
||||
status, hypervisors []string,
|
||||
pendingDelete bool,
|
||||
) Usage {
|
||||
hostType := ""
|
||||
if len(hostTypes) != 0 {
|
||||
hostType = hostTypes[0]
|
||||
}
|
||||
projectId := ""
|
||||
if userCred != nil {
|
||||
projectId = userCred.GetProjectId()
|
||||
}
|
||||
guest := models.GuestManager.TotalCount(projectId, rangeObj, status, hypervisors, true, pendingDelete, hostType)
|
||||
guest := models.GuestManager.TotalCount(projectId, rangeObj, status, hypervisors, true, pendingDelete, hostTypes, resourceTypes, providers)
|
||||
count := make(map[string]interface{})
|
||||
count[prefix] = guest.TotalGuestCount
|
||||
count[fmt.Sprintf("%s.cpu", prefix)] = guest.TotalCpuCount
|
||||
@@ -430,34 +523,60 @@ func guestHypervisorsUsage(
|
||||
count[fmt.Sprintf("%s.disk", prefix)] = guest.TotalDiskSize
|
||||
count[fmt.Sprintf("%s.isolated_devices", prefix)] = guest.TotalIsolatedCount
|
||||
|
||||
count[fmt.Sprintf("%s.ha", prefix)] = guest.TotalBackupGuestCount
|
||||
count[fmt.Sprintf("%s.ha.cpu", prefix)] = guest.TotalBackupCpuCount
|
||||
count[fmt.Sprintf("%s.ha.memory", prefix)] = guest.TotalBackupMemSize
|
||||
count[fmt.Sprintf("%s.ha.disk", prefix)] = guest.TotalBackupDiskSize
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
func guestUsage(prefix string, userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel, hostTypes, status []string, pendingDelete bool) Usage {
|
||||
func guestUsage(prefix string, userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel,
|
||||
hostTypes []string, resourceTypes []string, providers []string,
|
||||
status []string, pendingDelete bool) Usage {
|
||||
hypervisors := sets.NewString(models.HYPERVISORS...)
|
||||
hypervisors.Delete(models.HYPERVISOR_CONTAINER)
|
||||
return guestHypervisorsUsage(prefix, userCred, rangeObj, hostTypes, status, hypervisors.List(), pendingDelete)
|
||||
return guestHypervisorsUsage(prefix, userCred, rangeObj, hostTypes, resourceTypes, providers, status, hypervisors.List(), pendingDelete)
|
||||
}
|
||||
|
||||
func containerUsage(prefix string, userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel) Usage {
|
||||
func containerUsage(prefix string, userCred mcclient.TokenCredential, rangeObj db.IStandaloneModel,
|
||||
hostTypes []string, resourceTypes []string, providers []string) Usage {
|
||||
hypervisors := []string{models.HYPERVISOR_CONTAINER}
|
||||
return guestHypervisorsUsage(prefix, userCred, rangeObj, nil, nil, hypervisors, false)
|
||||
return guestHypervisorsUsage(prefix, userCred, rangeObj, hostTypes, resourceTypes, providers, nil, hypervisors, false)
|
||||
}
|
||||
|
||||
func IsolatedDeviceUsage(rangeObj db.IStandaloneModel, hostType []string) Usage {
|
||||
func IsolatedDeviceUsage(pref string, rangeObj db.IStandaloneModel, hostType []string, resourceTypes []string, providers []string) Usage {
|
||||
prefix := "isolated_devices"
|
||||
ret := models.IsolatedDeviceManager.TotalCount(hostType, rangeObj)
|
||||
if len(pref) > 0 {
|
||||
prefix = fmt.Sprintf("%s.%s", prefix, pref)
|
||||
}
|
||||
ret := models.IsolatedDeviceManager.TotalCount(hostType, resourceTypes, providers, rangeObj)
|
||||
count := make(map[string]interface{})
|
||||
count[prefix] = ret.Devices
|
||||
return count
|
||||
}
|
||||
|
||||
func EipUsage(rangeObj db.IStandaloneModel, hostTypes []string) Usage {
|
||||
eipUsage := models.ElasticipManager.TotalCount("", rangeObj, hostTypes)
|
||||
func getKey(projectId, key string) string {
|
||||
if len(projectId) > 0 {
|
||||
return key
|
||||
} else {
|
||||
return fmt.Sprintf("all.%s", key)
|
||||
}
|
||||
}
|
||||
|
||||
func EipUsage(projectId string, rangeObj db.IStandaloneModel, providers []string) Usage {
|
||||
eipUsage := models.ElasticipManager.TotalCount(projectId, rangeObj, providers)
|
||||
count := make(map[string]interface{})
|
||||
count["eip.all"] = eipUsage.Total()
|
||||
count["eip.public_ip"] = eipUsage.PublicIPCount
|
||||
count["eip.floating_ip"] = eipUsage.EIPCount
|
||||
count["eip.floating_ip.used"] = eipUsage.EIPUsedCount
|
||||
count[getKey(projectId, "eip")] = eipUsage.Total()
|
||||
count[getKey(projectId, "eip.public_ip")] = eipUsage.PublicIPCount
|
||||
count[getKey(projectId, "eip.floating_ip")] = eipUsage.EIPCount
|
||||
count[getKey(projectId, "eip.floating_ip.used")] = eipUsage.EIPUsedCount
|
||||
return count
|
||||
}
|
||||
|
||||
func SnapshotUsage(projectId string, rangeObj db.IStandaloneModel, providers []string) Usage {
|
||||
cnt := models.TotalSnapshotCount(projectId, rangeObj, providers)
|
||||
count := make(map[string]interface{})
|
||||
count[getKey(projectId, "snapshot")] = cnt
|
||||
return count
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package lbagent // import "yunion.io/x/onecloud/pkg/lbagent"
|
||||
@@ -0,0 +1 @@
|
||||
package gobetween // import "yunion.io/x/onecloud/pkg/lbagent/gobetween"
|
||||
@@ -0,0 +1 @@
|
||||
package models // import "yunion.io/x/onecloud/pkg/lbagent/models"
|
||||
@@ -0,0 +1 @@
|
||||
package utils // import "yunion.io/x/onecloud/pkg/lbagent/utils"
|
||||
@@ -0,0 +1 @@
|
||||
package models // import "yunion.io/x/onecloud/pkg/mcclient/models"
|
||||
@@ -30,7 +30,7 @@ func init() {
|
||||
"Memory_size_mb", "Os_name", "Sys_disk_resizable", "Sys_disk_type",
|
||||
"Sys_disk_min_size_mb", "Sys_disk_max_size_mb", "Attached_disk_type",
|
||||
"Attached_disk_size_gb", "Attached_disk_count", "Data_disk_types",
|
||||
"Data_disk_max_count", "Nic_max_count", "Cloudregion_id", "Zone_id"},
|
||||
"Data_disk_max_count", "Nic_max_count", "Cloudregion_id", "Zone_id", "Provider"},
|
||||
[]string{})}
|
||||
|
||||
register(&CloudmetaSkus)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package options // import "yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
@@ -0,0 +1 @@
|
||||
package k8s // import "yunion.io/x/onecloud/pkg/mcclient/options/k8s"
|
||||
@@ -3,10 +3,11 @@ package options
|
||||
import "yunion.io/x/jsonutils"
|
||||
|
||||
type ScheduleOptions struct {
|
||||
Zone string `help:"Preferred zone where virtual server should be created" json:"prefer_zone"`
|
||||
Host string `help:"Preferred host where virtual server should be created" json:"prefer_host"`
|
||||
Schedtag []string `help:"Schedule policy, key = aggregate name, value = require|exclude|prefer|avoid" metavar:"<KEY:VALUE>"`
|
||||
Hypervisor string `help:"Hypervisor type" choices:"kvm|esxi|baremetal|container|aliyun|azure|qcloud|aws"`
|
||||
Zone string `help:"Preferred zone where virtual server should be created" json:"prefer_zone"`
|
||||
Host string `help:"Preferred host where virtual server should be created" json:"prefer_host"`
|
||||
Schedtag []string `help:"Schedule policy, key = aggregate name, value = require|exclude|prefer|avoid" metavar:"<KEY:VALUE>"`
|
||||
Hypervisor string `help:"Hypervisor type" choices:"kvm|esxi|baremetal|container|aliyun|azure|qcloud|aws|huawei"`
|
||||
ResourceType string `help:"Resource type" choices:"shared|prepaid|dedicated"`
|
||||
}
|
||||
|
||||
func (opts *ScheduleOptions) Params() (*jsonutils.JSONDict, error) {
|
||||
|
||||
@@ -24,6 +24,10 @@ type ServerListOptions struct {
|
||||
WithEip *bool `help:"Show Servers with EIP"`
|
||||
WithoutEip *bool `help:"Show Servers without EIP"`
|
||||
|
||||
ResourceType string `help:"Resource type" choices:"shared|prepaid|dedicated"`
|
||||
|
||||
BillingType string `help:"billing type" choices:"postpaid|prepaid"`
|
||||
|
||||
BaseListOptions
|
||||
}
|
||||
|
||||
@@ -90,8 +94,9 @@ func ParseServerDeployInfoList(list []string) (*jsonutils.JSONDict, error) {
|
||||
|
||||
type ServerCreateOptions struct {
|
||||
ScheduleOptions
|
||||
NAME string `help:"Name of server"`
|
||||
MEM string `help:"Memory size" metavar:"MEMORY" json:"vmem_size"`
|
||||
|
||||
NAME string `help:"Name of server" json:"-"`
|
||||
MEMSPEC string `help:"Memory size Or Instance Type" metavar:"MEMSPEC" json:"-"`
|
||||
Disk []string `help:"Disk descriptions" nargs:"+"`
|
||||
Net []string `help:"Network descriptions" metavar:"NETWORK"`
|
||||
IsolatedDevice []string `help:"Isolated device model or ID" metavar:"ISOLATED_DEVICE"`
|
||||
@@ -120,6 +125,10 @@ type ServerCreateOptions struct {
|
||||
DryRun *bool `help:"Dry run to test scheduler" json:"-"`
|
||||
RaidConfig []string `help:"Baremetal raid config" json:"-"`
|
||||
UserDataFile string `help:"user_data file path" json:"-"`
|
||||
|
||||
Duration string `help:"valid duration of the server, e.g. 1H, 1D, 1W, 1M, 1Y, ADMIN ONLY option"`
|
||||
|
||||
GenerateName bool `help:"name is generated by pattern" json:"-"`
|
||||
}
|
||||
|
||||
func (opts *ServerCreateOptions) Params() (*jsonutils.JSONDict, error) {
|
||||
@@ -283,6 +292,7 @@ type ServerRebuildRootOptions struct {
|
||||
Password string `help:"Default user password"`
|
||||
NoAccountInit *bool `help:"Not reset account password"`
|
||||
AutoStart *bool `help:"Auto start server after it is created"`
|
||||
AllDisks *bool `help:"Rebuild all disks including data disks"`
|
||||
}
|
||||
|
||||
type ServerChangeConfigOptions struct {
|
||||
@@ -290,6 +300,8 @@ type ServerChangeConfigOptions struct {
|
||||
Ncpu *int `help:"New number of Virtual CPU cores" json:"vcpu_count"`
|
||||
Vmem string `help:"New memory size" json:"vmem_size"`
|
||||
Disk []string `help:"Data disk description, from the 1st data disk to the last one, empty string if no change for this data disk"`
|
||||
|
||||
InstanceType string `help:"Instance Type, e.g. S2.SMALL2 for qcloud"`
|
||||
}
|
||||
|
||||
type ServerResetOptions struct {
|
||||
|
||||
@@ -24,6 +24,7 @@ const (
|
||||
ErrNoMoreSpaceForUnspecificSplit = `no more space for an unspecific split`
|
||||
ErrSubtotalOfSplitExceedsDiskSize = `subtotal of split exceeds disk size`
|
||||
ErrBaremetalHasAlreadyBeenOccupied = `baremetal has already been occupied`
|
||||
ErrPrepaidHostOccupied = `prepaid host occupied`
|
||||
|
||||
ErrUnknown = `unknown error`
|
||||
)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package k8s // import "yunion.io/x/onecloud/pkg/scheduler/algorithm/predicates/k8s"
|
||||
@@ -0,0 +1,48 @@
|
||||
package predicates
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/core"
|
||||
)
|
||||
|
||||
type ResourceTypePredicate struct {
|
||||
BasePredicate
|
||||
}
|
||||
|
||||
func (p *ResourceTypePredicate) Name() string {
|
||||
return "resource_type"
|
||||
}
|
||||
|
||||
func (p *ResourceTypePredicate) Clone() core.FitPredicate {
|
||||
return &ResourceTypePredicate{}
|
||||
}
|
||||
|
||||
func (p *ResourceTypePredicate) PreExecute(u *core.Unit, cs []core.Candidater) (bool, error) {
|
||||
if u.SchedData().ResourceType == "" {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (p *ResourceTypePredicate) Execute(u *core.Unit, c core.Candidater) (bool, []core.PredicateFailureReason, error) {
|
||||
h := NewPredicateHelper(p, u, c)
|
||||
|
||||
d := u.SchedData()
|
||||
|
||||
hostResType := c.GetResourceType()
|
||||
reqResType := d.ResourceType
|
||||
if hostResType != reqResType {
|
||||
h.Exclude2("resource_type", hostResType, reqResType)
|
||||
}
|
||||
|
||||
if hostResType == models.HostResourceTypePrepaidRecycle {
|
||||
if c.GetGuestCount() == 0 {
|
||||
h.SetCapacity(1)
|
||||
} else {
|
||||
h.Exclude(ErrPrepaidHostOccupied)
|
||||
}
|
||||
}
|
||||
// TODO: support HostResourceTypeDedicated
|
||||
|
||||
return h.GetResult()
|
||||
}
|
||||
@@ -20,5 +20,6 @@ func baremetalPredicates() sets.String {
|
||||
factory.RegisterFitPredicate("d-BaremetalMemoryFilter", &predicatebm.MemoryPredicate{}),
|
||||
factory.RegisterFitPredicate("e-BaremetalStorageFilter", &predicatebm.StoragePredicate{}),
|
||||
factory.RegisterFitPredicate("f-BaremetalNetFilter", &predicatebm.NetworkPredicate{}),
|
||||
factory.RegisterFitPredicate("g-BaremetalResourceTypeFilter", &predicates.ResourceTypePredicate{}),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ func defaultPredicates() sets.String {
|
||||
factory.RegisterFitPredicate("i-GuestStorageFilter", &predicateguest.StoragePredicate{}),
|
||||
factory.RegisterFitPredicate("j-GuestNetworkFilter", &predicateguest.NetworkPredicate{}),
|
||||
factory.RegisterFitPredicate("k-GuestIsolatedDeviceFilter", &predicateguest.IsolatedDevicePredicate{}),
|
||||
factory.RegisterFitPredicate("l-GuestResourceTypeFilter", &predicates.ResourceTypePredicate{}),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
o "yunion.io/x/onecloud/cmd/scheduler/options"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
type Meta map[string]string
|
||||
@@ -94,6 +95,7 @@ type SchedData struct {
|
||||
ForGuests []*ForGuest `json:"for_guests"`
|
||||
GuestStatus string `json:"guest_status"`
|
||||
Hypervisor string `json:"hypervisor"`
|
||||
ResourceType string `json:"resource_type"`
|
||||
|
||||
// VM
|
||||
Groups []string `json:"group"`
|
||||
@@ -168,6 +170,10 @@ func NewSchedData(sjson *simplejson.Json, count int64, byTest bool) (*SchedData,
|
||||
}
|
||||
}
|
||||
|
||||
if resourceType, ok := sjson.CheckGet("resource_type"); ok {
|
||||
data.ResourceType = resourceType.MustString()
|
||||
}
|
||||
|
||||
data.Candidates = candidates
|
||||
|
||||
err := data.reviseSchedType(sjson)
|
||||
@@ -263,7 +269,8 @@ func (s *SchedData) reviseSchedType(sjson *simplejson.Json) error {
|
||||
}
|
||||
|
||||
func (d *SchedData) SkipDirtyMarkHost() bool {
|
||||
skipByHypervisor := d.IsPublicCloudProvider() || d.IsContainer || d.Hypervisor == SchedTypeContainer
|
||||
isSharePublicCloudProvider := d.IsPublicCloudProvider() && (d.ResourceType == "" || d.ResourceType == models.HostResourceTypeShared)
|
||||
skipByHypervisor := isSharePublicCloudProvider || d.IsContainer || d.Hypervisor == SchedTypeContainer
|
||||
skipByBackup := d.Backup
|
||||
return skipByHypervisor || skipByBackup
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/pkg/util/sets"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -16,10 +18,6 @@ const (
|
||||
SchedTypeHyperV = "hyperv"
|
||||
SchedTypeKvm = "kvm"
|
||||
HostHypervisorForKvm = "hypervisor"
|
||||
HostTypeAliyun = "aliyun"
|
||||
HostTypeAzure = "azure"
|
||||
HostTypeAws = "aws"
|
||||
HostTypeQcloud = "qcloud"
|
||||
HostTypeKubelet = "kubelet"
|
||||
|
||||
AggregateStrategyRequire = "require"
|
||||
@@ -49,12 +47,7 @@ var (
|
||||
AggregateStrategyAvoid,
|
||||
)
|
||||
|
||||
PublicCloudProviders = sets.NewString(
|
||||
HostTypeAliyun,
|
||||
HostTypeAzure,
|
||||
HostTypeAws,
|
||||
HostTypeQcloud,
|
||||
)
|
||||
PublicCloudProviders = sets.NewString(models.PUBLIC_CLOUD_HYPERVISORS...)
|
||||
|
||||
ValidGpuTypes = sets.NewString(
|
||||
GPU_HPC_TYPE,
|
||||
|
||||
+7
@@ -104,6 +104,13 @@ func (bd *BaremetalDesc) Get(key string) interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
func (bd *BaremetalDesc) GetGuestCount() int64 {
|
||||
if bd.ServerID == "" {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
func (bd *BaremetalDesc) XGet(key string, kind core.Kind) interface{} {
|
||||
return core.XGetCalculator(bd, key, kind)
|
||||
}
|
||||
|
||||
+29
-10
@@ -8,6 +8,7 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
cloudmodels "yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/api"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/db/models"
|
||||
)
|
||||
@@ -24,6 +25,7 @@ func (b *baseDesc) UUID() string {
|
||||
|
||||
type baseHostDesc struct {
|
||||
baseDesc
|
||||
models.BillingResourceBase
|
||||
|
||||
ManagerID *string `json:"manager_id"`
|
||||
Status string `json:"status"`
|
||||
@@ -44,6 +46,15 @@ type baseHostDesc struct {
|
||||
Aggregates []*models.Aggregate `json:"aggregates"`
|
||||
HostAggregates []*models.Aggregate `json:"host_aggregates"`
|
||||
Cloudprovider *models.Cloudprovider `json:"cloudprovider"`
|
||||
ResourceType string `json:"resource_type"`
|
||||
RealExternalId string `json:"real_external_id"`
|
||||
}
|
||||
|
||||
func reviseResourceType(resType string) string {
|
||||
if resType == "" {
|
||||
return cloudmodels.HostResourceTypeDefault
|
||||
}
|
||||
return resType
|
||||
}
|
||||
|
||||
func newBaseHostDesc(host *models.Host) (*baseHostDesc, error) {
|
||||
@@ -53,16 +64,19 @@ func newBaseHostDesc(host *models.Host) (*baseHostDesc, error) {
|
||||
Name: host.Name,
|
||||
UpdatedAt: host.UpdatedAt,
|
||||
},
|
||||
ManagerID: host.ManagerID,
|
||||
Status: host.Status,
|
||||
CPUCount: host.CPUCount,
|
||||
MemSize: host.MemSize,
|
||||
HostStatus: host.HostStatus,
|
||||
Enabled: host.Enabled,
|
||||
HostType: host.HostType,
|
||||
IsBaremetal: host.IsBaremetal,
|
||||
NodeCount: host.NodeCount,
|
||||
IsMaintenance: host.IsMaintenance,
|
||||
BillingResourceBase: host.BillingResourceBase,
|
||||
ManagerID: host.ManagerID,
|
||||
Status: host.Status,
|
||||
CPUCount: host.CPUCount,
|
||||
MemSize: host.MemSize,
|
||||
HostStatus: host.HostStatus,
|
||||
Enabled: host.Enabled,
|
||||
HostType: host.HostType,
|
||||
IsBaremetal: host.IsBaremetal,
|
||||
NodeCount: host.NodeCount,
|
||||
IsMaintenance: host.IsMaintenance,
|
||||
ResourceType: reviseResourceType(host.ResourceType),
|
||||
RealExternalId: host.RealExternalId,
|
||||
}
|
||||
|
||||
if err := desc.fillCloudProvider(host); err != nil {
|
||||
@@ -97,6 +111,7 @@ func (b baseHostDesc) GetSchedDesc() *jsonutils.JSONDict {
|
||||
desc.Add(jsonutils.NewString(b.HostType), "host_type")
|
||||
desc.Add(jsonutils.NewString(b.ZoneID), "zone_id")
|
||||
desc.Add(jsonutils.NewString(b.Zone), "zone")
|
||||
desc.Add(jsonutils.NewString(b.ResourceType), "resource_type")
|
||||
|
||||
if b.Cloudprovider != nil {
|
||||
p := b.Cloudprovider
|
||||
@@ -109,6 +124,10 @@ func (b baseHostDesc) GetSchedDesc() *jsonutils.JSONDict {
|
||||
return desc
|
||||
}
|
||||
|
||||
func (b baseHostDesc) GetResourceType() string {
|
||||
return b.ResourceType
|
||||
}
|
||||
|
||||
func (b *baseHostDesc) fillCloudProvider(host *models.Host) error {
|
||||
if host.ManagerID == nil {
|
||||
log.Debugf("Host %q manager id is empty, no cloud provider", host.Name)
|
||||
|
||||
+5
-1
@@ -224,6 +224,10 @@ func (h *HostDesc) Type() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (h *HostDesc) GetGuestCount() int64 {
|
||||
return h.GuestCount
|
||||
}
|
||||
|
||||
func (h *HostDesc) Get(key string) interface{} {
|
||||
switch key {
|
||||
case "ID":
|
||||
@@ -953,7 +957,7 @@ func (b *HostBuilder) build() ([]interface{}, error) {
|
||||
if len(errs) > 0 {
|
||||
//return nil, errors.NewAggregate(errs)
|
||||
err := errors.NewAggregate(errs)
|
||||
log.Warningf("Build schedule descs error: %s", err)
|
||||
log.V(4).Warningf("Build schedule descs error: %s", err)
|
||||
}
|
||||
|
||||
return schedDescs, nil
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/scheduler/api"
|
||||
)
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ type Candidater interface {
|
||||
GetHostAggregates() []*models.Aggregate
|
||||
|
||||
GetSchedDesc() *jsonutils.JSONDict
|
||||
GetGuestCount() int64
|
||||
GetResourceType() string
|
||||
}
|
||||
|
||||
// HostPriority represents the priority of scheduling to particular host, higher priority is better.
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type BillingResourceBase struct {
|
||||
BillingType string `json:"billing_type" gorm:"column:billing_type"`
|
||||
ExpiredAt time.Time `json:"expired_at" gorm:"column:expired_at;type:datetime"`
|
||||
BillingCycle string `json:"billing_cycle" gorm:"column:billing_cycle"`
|
||||
}
|
||||
@@ -20,6 +20,7 @@ var (
|
||||
|
||||
type Host struct {
|
||||
StandaloneModel
|
||||
BillingResourceBase
|
||||
|
||||
Rack string `json:"rack,omitempty" gorm:"column:rack"`
|
||||
Slots string `json:"slots,omitempty" gorm:"column:slots"`
|
||||
@@ -57,6 +58,9 @@ type Host struct {
|
||||
ManagerID *string `json:"manager_id" gorm:"column:manager_id"`
|
||||
IsMaintenance bool `json:"is_maintenance" gorm:"column:is_maintenance"`
|
||||
|
||||
ResourceType string `json:"resource_type" gorm:"column:resource_type"`
|
||||
RealExternalId string `json:"real_external_id" gorm:"column:real_external_id;type:varchar(256) CHARACTER SET utf8"`
|
||||
|
||||
// DECAPITATE
|
||||
ClusterID string `json:"cluster_id" gorm:"column:cluster_id"`
|
||||
PoolID string `json:"pool_id,omitempty" gorm:"column:pool_id"`
|
||||
|
||||
@@ -389,3 +389,26 @@ func (self *SDisk) GetExpiredAt() time.Time {
|
||||
func (self *SDisk) GetAccessPath() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDisk) Rebuild(ctx context.Context) error {
|
||||
err := self.storage.zone.region.rebuildDisk(self.DiskId)
|
||||
if err != nil {
|
||||
if isError(err, "IncorrectInstanceStatus") {
|
||||
return nil
|
||||
}
|
||||
log.Errorf("rebuild disk fail %s", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) rebuildDisk(diskId string) error {
|
||||
params := make(map[string]string)
|
||||
params["DiskId"] = diskId
|
||||
_, err := self.ecsRequest("ReInitDisk", params)
|
||||
if err != nil {
|
||||
log.Errorf("ReInitDisk %s fail %s", diskId, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+11
-9
@@ -7,6 +7,7 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
type SHost struct {
|
||||
@@ -166,8 +167,9 @@ func (self *SHost) GetInstanceById(instanceId string) (*SInstance, error) {
|
||||
|
||||
func (self *SHost) CreateVM(name string, imgId string, sysDiskSize int, cpu int, memMB int,
|
||||
vswitchId string, ipAddr string, desc string, passwd string,
|
||||
storageType string, diskSizes []int, publicKey string, secgroupId string, userData string) (cloudprovider.ICloudVM, error) {
|
||||
vmId, err := self._createVM(name, imgId, sysDiskSize, cpu, memMB, "", vswitchId, ipAddr, desc, passwd, storageType, diskSizes, publicKey, secgroupId, userData)
|
||||
storageType string, diskSizes []int, publicKey string, secgroupId string, userData string,
|
||||
bc *billing.SBillingCycle) (cloudprovider.ICloudVM, error) {
|
||||
vmId, err := self._createVM(name, imgId, sysDiskSize, cpu, memMB, "", vswitchId, ipAddr, desc, passwd, storageType, diskSizes, publicKey, secgroupId, userData, bc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -181,8 +183,9 @@ func (self *SHost) CreateVM(name string, imgId string, sysDiskSize int, cpu int,
|
||||
|
||||
func (self *SHost) CreateVM2(name string, imgId string, sysDiskSize int, instanceType string,
|
||||
vswitchId string, ipAddr string, desc string, passwd string,
|
||||
storageType string, diskSizes []int, publicKey string, secgroupId string, userData string) (cloudprovider.ICloudVM, error) {
|
||||
vmId, err := self._createVM(name, imgId, sysDiskSize, 0, 0, instanceType, vswitchId, ipAddr, desc, passwd, storageType, diskSizes, publicKey, secgroupId, userData)
|
||||
storageType string, diskSizes []int, publicKey string, secgroupId string,
|
||||
userData string, bc *billing.SBillingCycle) (cloudprovider.ICloudVM, error) {
|
||||
vmId, err := self._createVM(name, imgId, sysDiskSize, 0, 0, instanceType, vswitchId, ipAddr, desc, passwd, storageType, diskSizes, publicKey, secgroupId, userData, bc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -197,7 +200,7 @@ func (self *SHost) CreateVM2(name string, imgId string, sysDiskSize int, instanc
|
||||
func (self *SHost) _createVM(name string, imgId string, sysDiskSize int, cpu int, memMB int, instanceType string,
|
||||
vswitchId string, ipAddr string, desc string, passwd string,
|
||||
storageType string, diskSizes []int, publicKey string, secgroupId string,
|
||||
userData string) (string, error) {
|
||||
userData string, bc *billing.SBillingCycle) (string, error) {
|
||||
net := self.zone.getNetworkById(vswitchId)
|
||||
if net == nil {
|
||||
return "", fmt.Errorf("invalid switch ID %s", vswitchId)
|
||||
@@ -249,13 +252,12 @@ func (self *SHost) _createVM(name string, imgId string, sysDiskSize int, cpu int
|
||||
|
||||
if len(instanceType) > 0 {
|
||||
log.Debugf("Try instancetype : %s", instanceType)
|
||||
vmId, err := self.zone.region.CreateInstance(name, imgId, instanceType, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair, userData)
|
||||
vmId, err := self.zone.region.CreateInstance(name, imgId, instanceType, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair, userData, bc)
|
||||
if err != nil {
|
||||
log.Errorf("Failed for %s: %s", instanceType, err)
|
||||
return "", fmt.Errorf("Failed to create, specification %s not supported", instanceType)
|
||||
} else {
|
||||
return vmId, nil
|
||||
}
|
||||
return vmId, nil
|
||||
}
|
||||
|
||||
instanceTypes, err := self.zone.region.GetMatchInstanceTypes(cpu, memMB, 0, self.zone.ZoneId)
|
||||
@@ -269,7 +271,7 @@ func (self *SHost) _createVM(name string, imgId string, sysDiskSize int, cpu int
|
||||
for _, instType := range instanceTypes {
|
||||
instanceTypeId := instType.InstanceTypeId
|
||||
log.Debugf("Try instancetype : %s", instanceTypeId)
|
||||
vmId, err := self.zone.region.CreateInstance(name, imgId, instanceTypeId, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair, userData)
|
||||
vmId, err := self.zone.region.CreateInstance(name, imgId, instanceTypeId, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair, userData, bc)
|
||||
if err != nil {
|
||||
log.Errorf("Failed for %s: %s", instanceTypeId, err)
|
||||
} else {
|
||||
|
||||
@@ -12,8 +12,10 @@ import (
|
||||
|
||||
"context"
|
||||
|
||||
"sort"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -268,6 +270,29 @@ func (self *SInstance) getVpc() (*SVpc, error) {
|
||||
return self.host.zone.region.getVpc(self.VpcAttributes.VpcId)
|
||||
}
|
||||
|
||||
type byAttachedTime []SDisk
|
||||
|
||||
func (a byAttachedTime) Len() int { return len(a) }
|
||||
func (a byAttachedTime) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a byAttachedTime) Less(i, j int) bool {
|
||||
switch a[i].GetDiskType() {
|
||||
case models.DISK_TYPE_SYS:
|
||||
return true
|
||||
case models.DISK_TYPE_SWAP:
|
||||
switch a[j].GetDiskType() {
|
||||
case models.DISK_TYPE_SYS:
|
||||
return false
|
||||
case models.DISK_TYPE_DATA:
|
||||
return true
|
||||
}
|
||||
case models.DISK_TYPE_DATA:
|
||||
if a[j].GetDiskType() != models.DISK_TYPE_DATA {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return a[i].AttachedTime.Before(a[j].AttachedTime)
|
||||
}
|
||||
|
||||
func (self *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
disks, total, err := self.host.zone.region.GetDisks(self.InstanceId, "", "", nil, 0, 50)
|
||||
if err != nil {
|
||||
@@ -277,6 +302,11 @@ func (self *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
if total > len(disks) {
|
||||
disks, _, err = self.host.zone.region.GetDisks(self.InstanceId, "", "", nil, 0, total)
|
||||
}
|
||||
|
||||
sort.Sort(byAttachedTime(disks))
|
||||
|
||||
log.Debugf("%s", jsonutils.Marshal(&disks))
|
||||
|
||||
idisks := make([]cloudprovider.ICloudDisk, len(disks))
|
||||
for i := 0; i < len(disks); i += 1 {
|
||||
store, err := self.host.zone.getStorageByCategory(disks[i].Category)
|
||||
@@ -499,7 +529,7 @@ func (self *SRegion) GetInstance(instanceId string) (*SInstance, error) {
|
||||
|
||||
func (self *SRegion) CreateInstance(name string, imageId string, instanceType string, securityGroupId string,
|
||||
zoneId string, desc string, passwd string, disks []SDisk, vSwitchId string, ipAddr string,
|
||||
keypair string, userData string) (string, error) {
|
||||
keypair string, userData string, bc *billing.SBillingCycle) (string, error) {
|
||||
params := make(map[string]string)
|
||||
params["RegionId"] = self.RegionId
|
||||
params["ImageId"] = imageId
|
||||
@@ -535,8 +565,7 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st
|
||||
}
|
||||
params["VSwitchId"] = vSwitchId
|
||||
params["PrivateIpAddress"] = ipAddr
|
||||
params["InstanceChargeType"] = "PostPaid"
|
||||
params["SpotStrategy"] = "NoSpot"
|
||||
|
||||
if len(keypair) > 0 {
|
||||
params["KeyPairName"] = keypair
|
||||
}
|
||||
@@ -545,6 +574,21 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st
|
||||
params["UserData"] = userData
|
||||
}
|
||||
|
||||
if bc != nil {
|
||||
params["InstanceChargeType"] = "PrePaid"
|
||||
if bc.GetWeeks() <= 4 {
|
||||
params["PeriodUnit"] = "Week"
|
||||
params["Period"] = fmt.Sprintf("%d", bc.GetWeeks())
|
||||
} else {
|
||||
params["PeriodUnit"] = "Month"
|
||||
params["Period"] = fmt.Sprintf("%d", bc.GetMonths())
|
||||
}
|
||||
params["AutoRenew"] = "False"
|
||||
} else {
|
||||
params["InstanceChargeType"] = "PostPaid"
|
||||
params["SpotStrategy"] = "NoSpot"
|
||||
}
|
||||
|
||||
params["ClientToken"] = utils.GenRequestId(20)
|
||||
|
||||
body, err := self.ecsRequest("CreateInstance", params)
|
||||
@@ -620,6 +664,9 @@ func (self *SRegion) StopVM(instanceId string, isForce bool) error {
|
||||
log.Errorf("Fail to get instance status on StopVM: %s", err)
|
||||
return err
|
||||
}
|
||||
if status == InstanceStatusStopped {
|
||||
return nil
|
||||
}
|
||||
if status != InstanceStatusRunning {
|
||||
log.Errorf("StopVM: vm status is %s expect %s", status, InstanceStatusRunning)
|
||||
return cloudprovider.ErrInvalidStatus
|
||||
@@ -869,3 +916,26 @@ func (self *SInstance) UpdateUserData(userData string) error {
|
||||
func (self *SInstance) CreateDisk(ctx context.Context, sizeMb int, uuid string, driver string) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (self *SInstance) Renew(bc billing.SBillingCycle) error {
|
||||
return self.host.zone.region.RenewInstance(self.InstanceId, bc)
|
||||
}
|
||||
|
||||
func (region *SRegion) RenewInstance(instanceId string, bc billing.SBillingCycle) error {
|
||||
params := make(map[string]string)
|
||||
params["InstanceId"] = instanceId
|
||||
if bc.GetWeeks() <= 4 {
|
||||
params["PeriodUnit"] = "Week"
|
||||
params["Period"] = fmt.Sprintf("%s", bc.GetWeeks())
|
||||
} else {
|
||||
params["PeriodUnit"] = "Month"
|
||||
params["Period"] = fmt.Sprintf("%s", bc.GetMonths())
|
||||
}
|
||||
params["ClientToken"] = utils.GenRequestId(20)
|
||||
_, err := region.ecsRequest("RenewInstance", params)
|
||||
if err != nil {
|
||||
log.Errorf("RenewInstance fail %s", err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ func (self *SRegion) CreateInstanceSimple(name string, imgId string, cpu int, me
|
||||
log.Debugf("Search in zone %s", z.LocalName)
|
||||
net := z.getNetworkById(vswitchId)
|
||||
if net != nil {
|
||||
inst, err := z.getHost().CreateVM(name, imgId, 0, cpu, memGB*1024, vswitchId, "", "", passwd, storageType, dataDiskSizesGB, publicKey, "", "")
|
||||
inst, err := z.getHost().CreateVM(name, imgId, 0, cpu, memGB*1024, vswitchId, "", "", passwd, storageType, dataDiskSizesGB, publicKey, "", "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -396,7 +396,9 @@ func (self *SRegion) resetDisk(diskId, snapshotId string) error {
|
||||
}
|
||||
|
||||
params := &ec2.CreateVolumeInput{}
|
||||
params.SetSnapshotId(snapshotId)
|
||||
if len(snapshotId) > 0 {
|
||||
params.SetSnapshotId(snapshotId)
|
||||
}
|
||||
params.SetSize(int64(disk.Size))
|
||||
params.SetVolumeType(disk.Category)
|
||||
params.SetAvailabilityZone(disk.ZoneId)
|
||||
@@ -465,3 +467,7 @@ func (self *SRegion) CreateDisk(zoneId string, category string, name string, siz
|
||||
func (disk *SDisk) GetAccessPath() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDisk) Rebuild(ctx context.Context) error {
|
||||
return self.storage.zone.region.resetDisk(self.DiskId, "")
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package aws // import "yunion.io/x/onecloud/pkg/util/aws"
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
type SHost struct {
|
||||
@@ -56,7 +57,11 @@ func (self *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) {
|
||||
}
|
||||
|
||||
func (self *SHost) GetIVMById(gid string) (cloudprovider.ICloudVM, error) {
|
||||
log.Debugf("GetIVMById %s", gid)
|
||||
if len(gid) == 0 {
|
||||
log.Errorf("GetIVMById guest id is empty")
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
ivms, _, err := self.zone.region.GetInstances(self.zone.ZoneId, []string{gid}, 0, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -155,7 +160,8 @@ func (self *SHost) GetInstanceById(instanceId string) (*SInstance, error) {
|
||||
}
|
||||
|
||||
func (self *SHost) CreateVM(name, imgId string, sysDiskSize, cpu, memMB int, networkId, ipAddr, desc,
|
||||
passwd, storageType string, diskSizes []int, publicKey string, secgroupId string, userData string) (cloudprovider.ICloudVM, error) {
|
||||
passwd, storageType string, diskSizes []int, publicKey string, secgroupId string, userData string,
|
||||
bc *billing.SBillingCycle) (cloudprovider.ICloudVM, error) {
|
||||
vmId, err := self._createVM(name, imgId, sysDiskSize, cpu, memMB, "", networkId, ipAddr, desc, passwd, storageType, diskSizes, publicKey, secgroupId, userData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -170,7 +176,7 @@ func (self *SHost) CreateVM(name, imgId string, sysDiskSize, cpu, memMB int, net
|
||||
}
|
||||
|
||||
func (self *SHost) CreateVM2(name, imgId string, sysDiskSize int, instanceType string, networkId, ipAddr, desc,
|
||||
passwd, storageType string, diskSizes []int, publicKey string, secgroupId string, userData string) (cloudprovider.ICloudVM, error) {
|
||||
passwd, storageType string, diskSizes []int, publicKey string, secgroupId string, userData string, bc *billing.SBillingCycle) (cloudprovider.ICloudVM, error) {
|
||||
vmId, err := self._createVM(name, imgId, sysDiskSize, 0, 0, instanceType, networkId, ipAddr, desc, passwd, storageType, diskSizes, publicKey, secgroupId, userData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user