mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-30 18:23:35 +08:00
fix conflict
This commit is contained in:
Generated
+2
-2
@@ -1703,7 +1703,7 @@
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:04fac3de327ed7bf4490436dd3eb5fb10c7e80b919a109935d053f584fdb6566"
|
||||
digest = "1:65cac3daa80d78369c59b0e5ca4d8db352bf412db23767213e04f8c19dc822e1"
|
||||
name = "yunion.io/x/pkg"
|
||||
packages = [
|
||||
"gotypes",
|
||||
@@ -1737,7 +1737,7 @@
|
||||
"utils",
|
||||
]
|
||||
pruneopts = "UT"
|
||||
revision = "5d28ae811a2aaaed19efdc468573ef236b8327f9"
|
||||
revision = "e9943d77232072e08a77520fdc775dd29a43462e"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
||||
@@ -158,4 +158,13 @@ func init() {
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&CloudregionShowOptions{}, "cloud-region-capability", "Show region's capacibilities", func(s *mcclient.ClientSession, args *CloudregionShowOptions) error {
|
||||
result, err := modules.Cloudregions.GetSpecific(s, args.ID, "capability", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -157,31 +157,15 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type DiskCreateOptions struct {
|
||||
options.ScheduleOptions
|
||||
NAME string `help:"Name of the disk"`
|
||||
DISKDESC string `help:"Image size or size of virtual disk"`
|
||||
Desc string `help:"Description" metavar:"Description"`
|
||||
Storage string `help:"ID or name of storage where the disk is created"`
|
||||
TaskNotify bool `help:"Setup task notify"`
|
||||
}
|
||||
R(&DiskCreateOptions{}, "disk-create", "Create a virtual disk", func(s *mcclient.ClientSession, args *DiskCreateOptions) error {
|
||||
params, err := args.ScheduleOptions.Params()
|
||||
R(&options.DiskCreateOptions{}, "disk-create", "Create a virtual disk", func(s *mcclient.ClientSession, args *options.DiskCreateOptions) error {
|
||||
params, err := args.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params.Add(jsonutils.NewString(args.NAME), "name")
|
||||
params.Add(jsonutils.NewString(args.DISKDESC), "disk")
|
||||
if len(args.Desc) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Desc), "description")
|
||||
}
|
||||
if args.TaskNotify {
|
||||
s.PrepareTask()
|
||||
}
|
||||
if args.Storage != "" {
|
||||
params.Add(jsonutils.NewString(args.Storage), "storage")
|
||||
}
|
||||
disk, err := modules.Disks.Create(s, params)
|
||||
disk, err := modules.Disks.Create(s, params.JSON(params))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ func init() {
|
||||
Unused bool `help:"Only show unused devices"`
|
||||
Gpu bool `help:"Only show gpu devices"`
|
||||
Host string `help:"Host ID or Name"`
|
||||
Region string `help:"Cloudregion ID or Name"`
|
||||
Zone string `help:"Zone ID or Name"`
|
||||
}
|
||||
R(&DeviceListOptions{}, "isolated-device-list", "List isolated devices like GPU", func(s *mcclient.ClientSession, args *DeviceListOptions) error {
|
||||
@@ -35,6 +36,9 @@ func init() {
|
||||
if args.Gpu {
|
||||
params.Add(jsonutils.JSONTrue, "gpu")
|
||||
}
|
||||
if len(args.Region) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Region), "region")
|
||||
}
|
||||
if args.Zone != "" {
|
||||
params.Add(jsonutils.NewString(args.Zone), "zone")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
R(&options.MetadataListOptions{}, "metadata-list", "List metadatas", func(s *mcclient.ClientSession, opts *options.MetadataListOptions) error {
|
||||
params, err := options.ListStructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.Metadatas.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, []string{})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -1,64 +1,91 @@
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type SchedtagHostListOptions struct {
|
||||
options.BaseListOptions
|
||||
Schedtag string `help:"ID or Name of schedtag"`
|
||||
type schedtagModelHelper struct {
|
||||
managers []modules.JointResourceManager
|
||||
}
|
||||
|
||||
func newSchedtagModelHelper(mans ...modules.JointResourceManager) *schedtagModelHelper {
|
||||
return &schedtagModelHelper{managers: mans}
|
||||
}
|
||||
|
||||
func (h *schedtagModelHelper) register() {
|
||||
for _, man := range h.managers {
|
||||
h.list(man.Slave, man.Slave.GetKeyword())
|
||||
h.add(man, man.Slave.GetKeyword())
|
||||
h.remove(man, man.Slave.GetKeyword())
|
||||
}
|
||||
R(&SchedtagHostListOptions{}, "schedtag-host-list", "List all scheduler tag and host pairs", func(s *mcclient.ClientSession, args *SchedtagHostListOptions) error {
|
||||
mod, err := modules.GetJointModule2(s, &modules.Schedtags, &modules.Hosts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var params *jsonutils.JSONDict
|
||||
{
|
||||
var err error
|
||||
params, err = args.BaseListOptions.Params()
|
||||
}
|
||||
|
||||
func (h *schedtagModelHelper) list(slave modules.Manager, kw string) {
|
||||
R(
|
||||
&options.SchedtagModelListOptions{},
|
||||
fmt.Sprintf("schedtag-%s-list", kw),
|
||||
fmt.Sprintf("List all scheduler tag and %s pairs", kw),
|
||||
func(s *mcclient.ClientSession, args *options.SchedtagModelListOptions) error {
|
||||
mod, err := modules.GetJointModule2(s, &modules.Schedtags, slave)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
}
|
||||
var result *modules.ListResult
|
||||
if len(args.Schedtag) > 0 {
|
||||
result, err = mod.ListDescendent(s, args.Schedtag, params)
|
||||
} else {
|
||||
result, err = mod.List(s, params)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, mod.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
params, err := args.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var result *modules.ListResult
|
||||
if len(args.Schedtag) > 0 {
|
||||
result, err = mod.ListDescendent(s, args.Schedtag, params)
|
||||
} else {
|
||||
result, err = mod.List(s, params)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(result, mod.GetColumns(s))
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
type SchedtagHostPair struct {
|
||||
SCHEDTAG string `help:"Scheduler tag"`
|
||||
HOST string `help:"Host"`
|
||||
}
|
||||
R(&SchedtagHostPair{}, "schedtag-host-add", "Add a schedtag to a host", func(s *mcclient.ClientSession, args *SchedtagHostPair) error {
|
||||
schedtag, err := modules.Schedtaghosts.Attach(s, args.SCHEDTAG, args.HOST, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(schedtag)
|
||||
return nil
|
||||
})
|
||||
func (h *schedtagModelHelper) add(man modules.JointResourceManager, kw string) {
|
||||
R(
|
||||
&options.SchedtagModelPairOptions{},
|
||||
fmt.Sprintf("schedtag-%s-add", kw),
|
||||
fmt.Sprintf("Add a schedtag to a %s", kw),
|
||||
func(s *mcclient.ClientSession, args *options.SchedtagModelPairOptions) error {
|
||||
schedtag, err := man.Attach(s, args.SCHEDTAG, args.OBJECT, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(schedtag)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
R(&SchedtagHostPair{}, "schedtag-host-remove", "Remove a schedtag from a host", func(s *mcclient.ClientSession, args *SchedtagHostPair) error {
|
||||
schedtag, err := modules.Schedtaghosts.Detach(s, args.SCHEDTAG, args.HOST, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(schedtag)
|
||||
return nil
|
||||
})
|
||||
func (h *schedtagModelHelper) remove(man modules.JointResourceManager, kw string) {
|
||||
R(
|
||||
&options.SchedtagModelPairOptions{},
|
||||
fmt.Sprintf("schedtag-%s-remove", kw),
|
||||
fmt.Sprintf("Remove a schedtag to a %s", kw),
|
||||
func(s *mcclient.ClientSession, args *options.SchedtagModelPairOptions) error {
|
||||
schedtag, err := man.Detach(s, args.SCHEDTAG, args.OBJECT, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(schedtag)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func init() {
|
||||
newSchedtagModelHelper(
|
||||
modules.Schedtaghosts,
|
||||
modules.Schedtagstorages,
|
||||
).register()
|
||||
}
|
||||
|
||||
@@ -13,17 +13,21 @@ import (
|
||||
func init() {
|
||||
type SchedtagListOptions struct {
|
||||
options.BaseListOptions
|
||||
Type string `help:"Filter by resource type"`
|
||||
}
|
||||
R(&SchedtagListOptions{}, "schedtag-list", "List schedule tags", func(s *mcclient.ClientSession, suboptions *SchedtagListOptions) error {
|
||||
R(&SchedtagListOptions{}, "schedtag-list", "List schedule tags", func(s *mcclient.ClientSession, args *SchedtagListOptions) error {
|
||||
var params *jsonutils.JSONDict
|
||||
{
|
||||
var err error
|
||||
params, err = suboptions.BaseListOptions.Params()
|
||||
params, err = args.BaseListOptions.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
}
|
||||
if len(args.Type) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Type), "resource_type")
|
||||
}
|
||||
result, err := modules.Schedtags.List(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -57,6 +61,7 @@ func init() {
|
||||
NAME string `help:"Name of new schedtag"`
|
||||
Strategy string `help:"Policy" choices:"require|exclude|prefer|avoid"`
|
||||
Desc string `help:"Description"`
|
||||
Type string `help:"Resource type" choices:"hosts|storages"`
|
||||
}
|
||||
R(&SchedtagCreateOptions{}, "schedtag-create", "Create a schedule tag", func(s *mcclient.ClientSession, args *SchedtagCreateOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
@@ -67,6 +72,9 @@ func init() {
|
||||
if len(args.Desc) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Desc), "description")
|
||||
}
|
||||
if len(args.Type) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Type), "resource_type")
|
||||
}
|
||||
schedtag, err := modules.Schedtags.Create(s, params)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -35,7 +35,7 @@ func init() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.SchedManager.DoForecast(s, params)
|
||||
result, err := modules.SchedManager.DoForecast(s, params.JSON(params))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -45,6 +45,7 @@ func init() {
|
||||
|
||||
type SchedulerCandidateListOptions struct {
|
||||
Type string `help:"Sched type filter" choices:"baremetal|host"`
|
||||
Region string `help:"Cloud region ID"`
|
||||
Zone string `help:"Zone ID"`
|
||||
Limit int `default:"50" help:"Page limit"`
|
||||
Offset int `default:"0" help:"Page offset"`
|
||||
@@ -58,6 +59,9 @@ func init() {
|
||||
if args.Offset > 0 {
|
||||
params.Add(jsonutils.NewInt(int64(args.Offset)), "offset")
|
||||
}
|
||||
if len(args.Region) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Region), "region")
|
||||
}
|
||||
if len(args.Zone) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Zone), "zone")
|
||||
}
|
||||
|
||||
+40
-31
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
@@ -85,52 +84,62 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.ServerMetadataOptions{}, "server-add-tag", "Set tag of a server", func(s *mcclient.ClientSession, opts *options.ServerMetadataOptions) error {
|
||||
params, err := opts.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.Servers.PerformAction(s, opts.ID, "user-metadata", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.ServerMetadataOptions{}, "server-set-tag", "Set tag of a server", func(s *mcclient.ClientSession, opts *options.ServerMetadataOptions) error {
|
||||
params, err := opts.Params()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result, err := modules.Servers.PerformAction(s, opts.ID, "set-user-metadata", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(result)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&options.ServerCreateOptions{}, "server-create", "Create a server", func(s *mcclient.ClientSession, opts *options.ServerCreateOptions) error {
|
||||
params, err := opts.Params()
|
||||
if err != nil {
|
||||
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")
|
||||
}
|
||||
|
||||
if len(opts.UserDataFile) > 0 {
|
||||
userdata, err := ioutil.ReadFile(opts.UserDataFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params.Add(jsonutils.NewString(string(userdata)), "user_data")
|
||||
}
|
||||
|
||||
count := options.IntV(opts.Count)
|
||||
count := params.Count
|
||||
if options.BoolV(opts.DryRun) {
|
||||
results, err := modules.SchedManager.DoScheduleListResult(s, params, count)
|
||||
listFields := []string{"id", "name", "capacity", "count", "score", "capacity_details", "score_details"}
|
||||
input, err := opts.ToScheduleInput()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(results, []string{"id", "name", "rank", "capacity", "error"})
|
||||
result, err := modules.SchedManager.Test(s, input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(modules.JSON2ListResult(result), listFields)
|
||||
} else {
|
||||
taskNotify := options.BoolV(opts.TaskNotify)
|
||||
if taskNotify {
|
||||
s.PrepareTask()
|
||||
}
|
||||
if count > 1 {
|
||||
results := modules.Servers.BatchCreate(s, params, count)
|
||||
results := modules.Servers.BatchCreate(s, params.JSON(params), count)
|
||||
printBatchResults(results, modules.Servers.GetColumns(s))
|
||||
} else {
|
||||
server, err := modules.Servers.Create(s, params)
|
||||
server, err := modules.Servers.Create(s, params.JSON(params))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -358,7 +367,7 @@ func init() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srv, e := modules.Servers.PerformAction(s, opts.ID, "deploy", params)
|
||||
srv, e := modules.Servers.PerformAction(s, opts.ID, "deploy", params.JSON(params))
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
|
||||
+4
-3
@@ -9,7 +9,8 @@ import (
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon"
|
||||
app_common "yunion.io/x/onecloud/pkg/cloudcommon/app"
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
"yunion.io/x/onecloud/pkg/lbagent"
|
||||
)
|
||||
|
||||
@@ -17,8 +18,8 @@ func main() {
|
||||
opts := &lbagent.Options{}
|
||||
commonOpts := &opts.CommonOptions
|
||||
{
|
||||
cloudcommon.ParseOptions(opts, os.Args, "lbagent.conf", "lbagent")
|
||||
cloudcommon.InitAuth(commonOpts, func() {
|
||||
common_options.ParseOptions(opts, os.Args, "lbagent.conf", "lbagent")
|
||||
app_common.InitAuth(commonOpts, func() {
|
||||
log.Infof("auth finished ok")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package app // import "yunion.io/x/onecloud/cmd/scheduler/app"
|
||||
@@ -1,107 +0,0 @@
|
||||
// Package app implements a Server object for running the scheduler.
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
gin "gopkg.in/gin-gonic/gin.v1"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/prometheus"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
o "yunion.io/x/onecloud/cmd/scheduler/options"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
_ "yunion.io/x/onecloud/pkg/scheduler/algorithmprovider"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/db/models"
|
||||
schedhandler "yunion.io/x/onecloud/pkg/scheduler/handler"
|
||||
schedman "yunion.io/x/onecloud/pkg/scheduler/manager"
|
||||
"yunion.io/x/onecloud/pkg/util/gin/middleware"
|
||||
)
|
||||
|
||||
type SchedulerServer struct {
|
||||
Address string
|
||||
Port int32
|
||||
SQLConn string
|
||||
DBDialect string
|
||||
AuthInfo *auth.AuthInfo
|
||||
}
|
||||
|
||||
func NewServerFromConfig() *SchedulerServer {
|
||||
authURL := o.GetOptions().AuthURL
|
||||
adminUser := o.GetOptions().AdminUser
|
||||
adminPasswd := o.GetOptions().AdminPasswd
|
||||
adminTenant := o.GetOptions().AdminTenant
|
||||
a := auth.NewV2AuthInfo(authURL, adminUser, adminPasswd, adminTenant)
|
||||
|
||||
s := &SchedulerServer{}
|
||||
s.Address = o.GetOptions().Address
|
||||
s.Port = int32(o.GetOptions().Port)
|
||||
sqlDialect, sqlConn, err := utils.TransSQLAchemyURL(o.GetOptions().SqlConnection)
|
||||
if err != nil {
|
||||
log.Fatalf("Backup python sql_connection config err: %v", err)
|
||||
}
|
||||
s.SQLConn = sqlConn
|
||||
s.DBDialect = sqlDialect
|
||||
s.AuthInfo = a
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func Run(s *SchedulerServer) error {
|
||||
startSched := func() {
|
||||
err := models.Init(s.DBDialect, s.SQLConn)
|
||||
if err != nil {
|
||||
log.Fatalf("DB init error: %v, dialect: %s, url: %s", err, s.DBDialect, s.SQLConn)
|
||||
}
|
||||
|
||||
stopEverything := make(chan struct{})
|
||||
schedman.InitAndStart(stopEverything)
|
||||
}
|
||||
|
||||
debug := o.GetOptions().LogLevel == "debug"
|
||||
|
||||
auth.AsyncInit(s.AuthInfo, debug, true, "", "", startSched)
|
||||
|
||||
return startHTTP(s)
|
||||
}
|
||||
|
||||
func startHTTP(s *SchedulerServer) error {
|
||||
gin.DefaultWriter = ioutil.Discard
|
||||
|
||||
router := gin.Default()
|
||||
router.Use(middleware.Logger())
|
||||
router.Use(middleware.ErrorHandler)
|
||||
router.Use(middleware.KeystoneTokenVerifyMiddleware())
|
||||
|
||||
prometheus.InstallHandler(router)
|
||||
schedhandler.InstallHandler(router)
|
||||
|
||||
server := &http.Server{
|
||||
Addr: net.JoinHostPort(s.Address, strconv.Itoa(int(s.Port))),
|
||||
Handler: router,
|
||||
}
|
||||
|
||||
log.Infof("Start server on: %s:%d", s.Address, s.Port)
|
||||
|
||||
if o.GetOptions().EnableSsl {
|
||||
return server.ListenAndServeTLS(o.GetOptions().SslCertfile,
|
||||
o.GetOptions().SslKeyfile)
|
||||
} else {
|
||||
return server.ListenAndServe()
|
||||
}
|
||||
}
|
||||
|
||||
func Execute() error {
|
||||
o.Parse()
|
||||
|
||||
err := Run(NewServerFromConfig())
|
||||
if err != nil {
|
||||
err = fmt.Errorf("scheduler app failed to run: %v", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -5,11 +5,11 @@ import (
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/cmd/scheduler/app"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/service"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := app.Execute(); err != nil {
|
||||
if err := service.StartService(); err != nil {
|
||||
log.Errorln(err)
|
||||
os.Exit(-1)
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package options // import "yunion.io/x/onecloud/cmd/scheduler/options"
|
||||
@@ -0,0 +1,12 @@
|
||||
package apis
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
)
|
||||
|
||||
// Meta is embedded by every input or output params
|
||||
type Meta struct{}
|
||||
|
||||
func (m Meta) JSON(self interface{}) *jsonutils.JSONDict {
|
||||
return jsonutils.Marshal(self).(*jsonutils.JSONDict)
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type SchedtagConfig struct {
|
||||
apis.Meta
|
||||
|
||||
Id string `json:"id"`
|
||||
Strategy string `json:"strategy"`
|
||||
}
|
||||
|
||||
type NetworkConfig struct {
|
||||
apis.Meta
|
||||
|
||||
Index int `json:"index"`
|
||||
Network string `json:"network"`
|
||||
Wire string `json:"wire"`
|
||||
Exit bool `json:"exit"`
|
||||
Private bool `json:"private"`
|
||||
Mac string `json:"mac"`
|
||||
Address string `json:"address"`
|
||||
Address6 string `json:"address6"`
|
||||
Driver string `json:"driver"`
|
||||
BwLimit int `json:"bw_limit"`
|
||||
Vip bool `json:"vip"`
|
||||
Reserved bool `json:"reserved"`
|
||||
NetType string `json:"net_type"`
|
||||
|
||||
RequireTeaming bool `json:"require_teaming"`
|
||||
TryTeaming bool `json:"try_teaming"`
|
||||
|
||||
StandbyPortCount int `json:"standby_port_count"`
|
||||
StandbyAddrCount int `json:"standby_addr_count"`
|
||||
|
||||
Project string `json:"project"`
|
||||
Ifname string `json:"ifname"`
|
||||
}
|
||||
|
||||
type DiskConfig struct {
|
||||
apis.Meta
|
||||
|
||||
Index int `json:"index"` // -1 means not attach to any guests
|
||||
ImageId string `json:"image_id"`
|
||||
SnapshotId string `json:"snapshot_id"`
|
||||
DiskType string `json:"disk_type"`
|
||||
Schedtags []*SchedtagConfig `json:"schedtags"`
|
||||
|
||||
SizeMb int `json:"size"`
|
||||
Fs string `json:"fs"`
|
||||
Format string `json:"format"`
|
||||
Driver string `json:"driver"`
|
||||
Cache string `json:"cache"`
|
||||
Mountpoint string `json:"mountpoint"`
|
||||
Backend string `json:"backend"` // stroageType
|
||||
Medium string `json:"medium"`
|
||||
ImageProperties map[string]string `json:"image_properties"`
|
||||
|
||||
Storage string `json:"storage"`
|
||||
DiskId string `json:"disk_id"`
|
||||
}
|
||||
|
||||
type IsolatedDeviceConfig struct {
|
||||
Index int `json:"index"`
|
||||
Id string `json:"id"`
|
||||
DevType string `json:"dev_type"`
|
||||
Model string `json:"model"`
|
||||
Vendor string `json:"vendor"`
|
||||
}
|
||||
|
||||
type BaremetalDiskConfig struct {
|
||||
//Index int `json:"index"`
|
||||
// disk type
|
||||
Type string `json:"type"`
|
||||
// raid config
|
||||
Conf string `json:"conf"`
|
||||
Count int64 `json:"count"`
|
||||
Range []int64 `json:"range"`
|
||||
Splits string `json:"splits"`
|
||||
Size []int64 `json:"size"`
|
||||
Adapter *int `json:"adapter,omitempty"`
|
||||
Driver string `json:"driver"`
|
||||
Cachedbadbbu *bool `json:"cachedbadbbu,omitempty"`
|
||||
Strip *int64 `json:"strip,omitempty"`
|
||||
RA *bool `json:"ra,omitempty"`
|
||||
WT *bool `json:"wt,omitempty"`
|
||||
Direct *bool `json:"direct,omitempty"`
|
||||
}
|
||||
|
||||
type ServerConfigs struct {
|
||||
// prefer options
|
||||
PreferRegion string `json:"prefer_region_id"`
|
||||
PreferZone string `json:"prefer_zone_id"`
|
||||
PreferWire string `json:"prefer_wire_id"`
|
||||
PreferHost string `json:"prefer_host_id"`
|
||||
PreferBackupHost string `json:"prefer_backup_host"`
|
||||
|
||||
Hypervisor string `json:"hypervisor"`
|
||||
// ResourceType "shared|prepaid|dedicated"`
|
||||
ResourceType string `json:"resource_type"`
|
||||
Project string `json:"project"`
|
||||
Backup bool `json:"backup"`
|
||||
Count int `json:"count"`
|
||||
|
||||
Disks []*DiskConfig `json:"disks"`
|
||||
Networks []*NetworkConfig `json:"nets"`
|
||||
Schedtags []*SchedtagConfig `json:"schedtags"`
|
||||
IsolatedDevices []*IsolatedDeviceConfig `json:"isolated_devices"`
|
||||
BaremetalDiskConfigs []*BaremetalDiskConfig `json:"baremetal_disk_configs"`
|
||||
|
||||
// DEPRECATE
|
||||
Suggestion bool `json:"suggestion"`
|
||||
}
|
||||
|
||||
type DeployConfig struct {
|
||||
Action string `json:"action"`
|
||||
Path string `json:"path"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type ServerCreateInput struct {
|
||||
apis.Meta
|
||||
|
||||
*ServerConfigs
|
||||
|
||||
Name string `json:"name"`
|
||||
GenerateName string `json:"generate_name"`
|
||||
VmemSize int `json:"vmem_size"`
|
||||
VcpuCount int `json:"vcpu_count"`
|
||||
InstanceType string `json:"instance_type"`
|
||||
UserData string `json:"user_data"`
|
||||
|
||||
Keypair string `json:"keypair"`
|
||||
Password string `json:"password"`
|
||||
Cdrom string `json:"cdrom"`
|
||||
Vga string `json:"vga"`
|
||||
Vdi string `json:"vdi"`
|
||||
Bios string `json:"bios"`
|
||||
Description string `json:"description"`
|
||||
BootOrder string `json:"boot_order"`
|
||||
ResetPassword *bool `json:"reset_password"`
|
||||
DisableDelete bool `json:"disable_delete"`
|
||||
ShutdownBehavior string `json:"shutdown_behavior"`
|
||||
AutoStart bool `json:"auto_start"`
|
||||
DeployConfigs []*DeployConfig `json:"deploy_configs"`
|
||||
IsSystem bool `json:"is_system"`
|
||||
Duration string `json:"duration"`
|
||||
AutoPrepaidRecycle bool `json:"auto_prepaid_recycle,omitfalse"`
|
||||
Secgroup string `json:"secgroup"`
|
||||
EipBw int `json:"eip_bw,omitzero"`
|
||||
EipChargeType string `json:"eip_charge_type,omitempty"`
|
||||
Eip string `json:"eip,omitempty"`
|
||||
|
||||
OsType string `json:"os_type"`
|
||||
// Fill by server
|
||||
OsProfile jsonutils.JSONObject `json:"__os_profile__"`
|
||||
BillingType string `json:"billing_type"`
|
||||
BillingCycle string `json:"billing_cycle"`
|
||||
|
||||
// DEPRECATE or not used fields
|
||||
Baremetal bool `json:"baremetal"`
|
||||
}
|
||||
|
||||
type ServerDeployInput struct {
|
||||
apis.Meta
|
||||
|
||||
Id string
|
||||
|
||||
Keypair string `json:"keypair"`
|
||||
DeleteKeypair bool `json:"__delete_keypair__"`
|
||||
DeployConfigs []*DeployConfig `json:"deploy_configs"`
|
||||
ResetPassword *bool `json:"reset_password"`
|
||||
Password string `json:"password"`
|
||||
AutoStart *bool `json:"auto_start"`
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/util/sets"
|
||||
)
|
||||
|
||||
const (
|
||||
DISK_CONF_RAID0 = "raid0"
|
||||
DISK_CONF_RAID1 = "raid1"
|
||||
DISK_CONF_RAID5 = "raid5"
|
||||
DISK_CONF_RAID10 = "raid10"
|
||||
DISK_CONF_NONE = "none"
|
||||
|
||||
DEFAULT_DISK_CONF = DISK_CONF_NONE
|
||||
|
||||
DEFAULT_DISK_TYPE = DISK_TYPE_ROTATE
|
||||
|
||||
DISK_DRIVER_MEGARAID = "MegaRaid"
|
||||
DISK_DRIVER_LINUX = "Linux"
|
||||
DISK_DRIVER_HPSARAID = "HPSARaid"
|
||||
DISK_DRIVER_MPT2SAS = "Mpt2SAS"
|
||||
DISK_DRIVER_MARVELRAID = "MarvelRaid"
|
||||
DISK_DRIVER_PCIE = "PCIE"
|
||||
|
||||
HDD_DISK_SPEC_TYPE = "HDD"
|
||||
SSD_DISK_SPEC_TYPE = "SSD"
|
||||
)
|
||||
|
||||
var (
|
||||
BaremetalDefaultDiskConfig = BaremetalDiskConfig{
|
||||
Type: DISK_TYPE_HYBRID,
|
||||
Conf: DISK_CONF_NONE,
|
||||
Count: 0,
|
||||
}
|
||||
|
||||
DISK_CONFS = sets.NewString(
|
||||
DISK_CONF_RAID0,
|
||||
DISK_CONF_RAID1,
|
||||
DISK_CONF_RAID5,
|
||||
DISK_CONF_RAID10,
|
||||
DISK_CONF_NONE,
|
||||
)
|
||||
|
||||
DISK_DRIVERS_RAID = sets.NewString(
|
||||
DISK_DRIVER_MEGARAID,
|
||||
DISK_DRIVER_HPSARAID,
|
||||
DISK_DRIVER_MPT2SAS,
|
||||
DISK_DRIVER_MARVELRAID,
|
||||
)
|
||||
|
||||
DISK_DRIVERS = sets.NewString(
|
||||
DISK_DRIVER_LINUX,
|
||||
DISK_DRIVER_PCIE).Union(DISK_DRIVERS_RAID)
|
||||
)
|
||||
@@ -0,0 +1,51 @@
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type DiskCreateInput struct {
|
||||
apis.Meta
|
||||
|
||||
*DiskConfig
|
||||
|
||||
// prefer options
|
||||
PreferRegion string `json:"prefer_region_id"`
|
||||
PreferZone string `json:"prefer_zone_id"`
|
||||
PreferWire string `json:"prefer_wire_id"`
|
||||
PreferHost string `json:"prefer_host_id"`
|
||||
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Hypervisor string `json:"hypervisor"`
|
||||
Project string `json:"project"`
|
||||
}
|
||||
|
||||
// ToServerCreateInput used by disk schedule
|
||||
func (req *DiskCreateInput) ToServerCreateInput() *ServerCreateInput {
|
||||
return &ServerCreateInput{
|
||||
ServerConfigs: &ServerConfigs{
|
||||
PreferRegion: req.PreferRegion,
|
||||
PreferZone: req.PreferZone,
|
||||
PreferWire: req.PreferWire,
|
||||
PreferHost: req.PreferHost,
|
||||
Hypervisor: req.Hypervisor,
|
||||
Disks: []*DiskConfig{req.DiskConfig},
|
||||
Project: req.Project,
|
||||
},
|
||||
Name: req.Name,
|
||||
}
|
||||
}
|
||||
|
||||
func (req *ServerCreateInput) ToDiskCreateInput() *DiskCreateInput {
|
||||
return &DiskCreateInput{
|
||||
DiskConfig: req.Disks[0],
|
||||
PreferRegion: req.PreferRegion,
|
||||
PreferHost: req.PreferHost,
|
||||
PreferZone: req.PreferZone,
|
||||
PreferWire: req.PreferWire,
|
||||
Name: req.Name,
|
||||
Project: req.Project,
|
||||
Hypervisor: req.Hypervisor,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package compute
|
||||
|
||||
const (
|
||||
DISK_INIT = "init"
|
||||
DISK_REBUILD = "rebuild"
|
||||
DISK_ALLOC_FAILED = "alloc_failed"
|
||||
DISK_STARTALLOC = "start_alloc"
|
||||
DISK_BACKUP_STARTALLOC = "backup_start_alloc"
|
||||
DISK_BACKUP_ALLOC_FAILED = "backup_alloc_failed"
|
||||
DISK_ALLOCATING = "allocating"
|
||||
DISK_READY = "ready"
|
||||
DISK_RESET = "reset"
|
||||
DISK_RESET_FAILED = "reset_failed"
|
||||
DISK_DEALLOC = "deallocating"
|
||||
DISK_DEALLOC_FAILED = "dealloc_failed"
|
||||
DISK_UNKNOWN = "unknown"
|
||||
DISK_DETACHING = "detaching"
|
||||
DISK_ATTACHING = "attaching"
|
||||
DISK_CLONING = "cloning" // 硬盘克隆
|
||||
|
||||
DISK_START_SAVE = "start_save"
|
||||
DISK_SAVING = "saving"
|
||||
|
||||
DISK_START_RESIZE = "start_resize"
|
||||
DISK_RESIZING = "resizing"
|
||||
|
||||
DISK_START_MIGRATE = "start_migrate"
|
||||
DISK_POST_MIGRATE = "post_migrate"
|
||||
DISK_MIGRATING = "migrating"
|
||||
|
||||
DISK_START_SNAPSHOT = "start_snapshot"
|
||||
DISK_SNAPSHOTING = "snapshoting"
|
||||
|
||||
DISK_TYPE_SYS = "sys"
|
||||
DISK_TYPE_SWAP = "swap"
|
||||
DISK_TYPE_DATA = "data"
|
||||
DISK_TYPE_VOLUME = "volume"
|
||||
|
||||
DISK_BACKING_IMAGE = "image"
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
package compute // import "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -0,0 +1,65 @@
|
||||
package compute
|
||||
|
||||
const (
|
||||
HOST_TYPE_BAREMETAL = "baremetal"
|
||||
HOST_TYPE_HYPERVISOR = "hypervisor" // KVM
|
||||
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_HUAWEI = "huawei"
|
||||
HOST_TYPE_OPENSTACK = "openstack"
|
||||
HOST_TYPE_UCLOUD = "ucloud"
|
||||
|
||||
HOST_TYPE_DEFAULT = HOST_TYPE_HYPERVISOR
|
||||
|
||||
// # possible status
|
||||
HOST_ONLINE = "online"
|
||||
HOST_ENABLED = "online"
|
||||
HOST_OFFLINE = "offline"
|
||||
HOST_DISABLED = "offline"
|
||||
|
||||
NIC_TYPE_IPMI = "ipmi"
|
||||
NIC_TYPE_ADMIN = "admin"
|
||||
// #NIC_TYPE_NORMAL = 'normal'
|
||||
|
||||
BAREMETAL_INIT = "init"
|
||||
BAREMETAL_PREPARE = "prepare"
|
||||
BAREMETAL_PREPARE_FAIL = "prepare_fail"
|
||||
BAREMETAL_READY = "ready"
|
||||
BAREMETAL_RUNNING = "running"
|
||||
BAREMETAL_MAINTAINING = "maintaining"
|
||||
BAREMETAL_START_MAINTAIN = "start_maintain"
|
||||
BAREMETAL_DELETING = "deleting"
|
||||
BAREMETAL_DELETE = "delete"
|
||||
BAREMETAL_DELETE_FAIL = "delete_fail"
|
||||
BAREMETAL_UNKNOWN = "unknown"
|
||||
BAREMETAL_SYNCING_STATUS = "syncing_status"
|
||||
BAREMETAL_SYNC = "sync"
|
||||
BAREMETAL_SYNC_FAIL = "sync_fail"
|
||||
BAREMETAL_START_CONVERT = "start_convert"
|
||||
BAREMETAL_CONVERTING = "converting"
|
||||
BAREMETAL_START_FAIL = "start_fail"
|
||||
BAREMETAL_STOP_FAIL = "stop_fail"
|
||||
|
||||
HOST_STATUS_RUNNING = BAREMETAL_RUNNING
|
||||
HOST_STATUS_READY = BAREMETAL_READY
|
||||
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, HOST_TYPE_HUAWEI, HOST_TYPE_OPENSTACK}
|
||||
|
||||
var NIC_TYPES = []string{NIC_TYPE_IPMI, NIC_TYPE_ADMIN}
|
||||
@@ -0,0 +1,26 @@
|
||||
package compute
|
||||
|
||||
const (
|
||||
DIRECT_PCI_TYPE = "PCI"
|
||||
GPU_HPC_TYPE = "GPU-HPC" // # for compute
|
||||
GPU_VGA_TYPE = "GPU-VGA" // # for display
|
||||
USB_TYPE = "USB"
|
||||
NIC_TYPE = "NIC"
|
||||
|
||||
NVIDIA_VENDOR_ID = "10de"
|
||||
AMD_VENDOR_ID = "1002"
|
||||
)
|
||||
|
||||
var VALID_GPU_TYPES = []string{GPU_HPC_TYPE, GPU_VGA_TYPE}
|
||||
|
||||
var VALID_PASSTHROUGH_TYPES = []string{DIRECT_PCI_TYPE, USB_TYPE, NIC_TYPE, GPU_HPC_TYPE, GPU_VGA_TYPE}
|
||||
|
||||
var ID_VENDOR_MAP = map[string]string{
|
||||
NVIDIA_VENDOR_ID: "NVIDIA",
|
||||
AMD_VENDOR_ID: "AMD",
|
||||
}
|
||||
|
||||
var VENDOR_ID_MAP = map[string]string{
|
||||
"NVIDIA": NVIDIA_VENDOR_ID,
|
||||
"AMD": AMD_VENDOR_ID,
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package consts
|
||||
package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/util/choices"
|
||||
@@ -0,0 +1,38 @@
|
||||
package compute
|
||||
|
||||
const (
|
||||
// # DEFAULT_BANDWIDTH = options.default_bandwidth
|
||||
MAX_BANDWIDTH = 100000
|
||||
|
||||
NETWORK_TYPE_GUEST = "guest"
|
||||
NETWORK_TYPE_BAREMETAL = "baremetal"
|
||||
NETWORK_TYPE_CONTAINER = "container"
|
||||
NETWORK_TYPE_PXE = "pxe"
|
||||
NETWORK_TYPE_IPMI = "ipmi"
|
||||
|
||||
STATIC_ALLOC = "static"
|
||||
|
||||
MAX_NETWORK_NAME_LEN = 11
|
||||
|
||||
EXTRA_DNS_UPDATE_TARGETS = "__extra_dns_update_targets"
|
||||
|
||||
NETWORK_STATUS_INIT = "init"
|
||||
NETWORK_STATUS_PENDING = "pending"
|
||||
NETWORK_STATUS_AVAILABLE = "available"
|
||||
NETWORK_STATUS_FAILED = "failed"
|
||||
NETWORK_STATUS_UNKNOWN = "unknown"
|
||||
NETWORK_STATUS_START_DELETE = "start_delete"
|
||||
NETWORK_STATUS_DELETING = "deleting"
|
||||
NETWORK_STATUS_DELETED = "deleted"
|
||||
NETWORK_STATUS_DELETE_FAILED = "delete_failed"
|
||||
)
|
||||
|
||||
var (
|
||||
ALL_NETWORK_TYPES = []string{
|
||||
NETWORK_TYPE_GUEST,
|
||||
NETWORK_TYPE_BAREMETAL,
|
||||
NETWORK_TYPE_CONTAINER,
|
||||
NETWORK_TYPE_PXE,
|
||||
NETWORK_TYPE_IPMI,
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
package compute
|
||||
|
||||
const (
|
||||
STRATEGY_REQUIRE = "require"
|
||||
STRATEGY_EXCLUDE = "exclude"
|
||||
STRATEGY_PREFER = "prefer"
|
||||
STRATEGY_AVOID = "avoid"
|
||||
|
||||
// # container used aggregate
|
||||
CONTAINER_AGGREGATE = "container"
|
||||
)
|
||||
|
||||
var STRATEGY_LIST = []string{STRATEGY_REQUIRE, STRATEGY_EXCLUDE, STRATEGY_PREFER, STRATEGY_AVOID}
|
||||
@@ -0,0 +1,82 @@
|
||||
package compute
|
||||
|
||||
const (
|
||||
STORAGE_LOCAL = "local"
|
||||
STORAGE_BAREMETAL = "baremetal"
|
||||
STORAGE_SHEEPDOG = "sheepdog"
|
||||
STORAGE_RBD = "rbd"
|
||||
STORAGE_DOCKER = "docker"
|
||||
STORAGE_NAS = "nas"
|
||||
STORAGE_VSAN = "vsan"
|
||||
STORAGE_NFS = "nfs"
|
||||
|
||||
STORAGE_PUBLIC_CLOUD = "cloud"
|
||||
STORAGE_CLOUD_EFFICIENCY = "cloud_efficiency"
|
||||
STORAGE_CLOUD_SSD = "cloud_ssd"
|
||||
STORAGE_CLOUD_ESSD = "cloud_essd" //增强型(Enhanced)SSD 云盘
|
||||
STORAGE_EPHEMERAL_SSD = "ephemeral_ssd" //单块本地SSD盘, 容量最大不能超过800 GiB
|
||||
|
||||
//Azure hdd and ssd storagetype
|
||||
STORAGE_STANDARD_LRS = "standard_lrs"
|
||||
STORAGE_STANDARDSSD_LRS = "standardssd_lrs"
|
||||
STORAGE_PREMIUM_LRS = "premium_lrs"
|
||||
|
||||
// aws storage type
|
||||
STORAGE_GP2_SSD = "gp2" // aws general purpose ssd
|
||||
STORAGE_IO1_SSD = "io1" // aws Provisioned IOPS SSD
|
||||
STORAGE_ST1_HDD = "st1" // aws Throughput Optimized HDD
|
||||
STORAGE_SC1_HDD = "sc1" // aws Cold HDD
|
||||
STORAGE_STANDARD_HDD = "standard" // aws Magnetic volumes
|
||||
|
||||
// qcloud storage type
|
||||
// STORAGE_CLOUD_SSD ="cloud_ssd"
|
||||
STORAGE_LOCAL_BASIC = "local_basic"
|
||||
STORAGE_LOCAL_SSD = "local_ssd"
|
||||
STORAGE_CLOUD_BASIC = "cloud_basic"
|
||||
STORAGE_CLOUD_PREMIUM = "cloud_premium"
|
||||
|
||||
// huawei storage type
|
||||
STORAGE_HUAWEI_SSD = "SSD" // 超高IO云硬盘
|
||||
STORAGE_HUAWEI_SAS = "SAS" // 高IO云硬盘
|
||||
STORAGE_HUAWEI_SATA = "SATA" // 普通IO云硬盘
|
||||
|
||||
// openstack
|
||||
STORAGE_OPENSTACK_ISCSI = "iscsi"
|
||||
|
||||
// Ucloud storage type
|
||||
STORAGE_UCLOUD_SATA = "SATA" // 普通盘
|
||||
STORAGE_UCLOUD_SSD = "SSD" // SSD盘
|
||||
)
|
||||
|
||||
const (
|
||||
STORAGE_ENABLED = "enabled"
|
||||
// STORAGE_DISABLED = "disabled"
|
||||
STORAGE_OFFLINE = "offline"
|
||||
STORAGE_ONLINE = "online"
|
||||
|
||||
DISK_TYPE_ROTATE = "rotate"
|
||||
DISK_TYPE_SSD = "ssd"
|
||||
DISK_TYPE_HYBRID = "hybrid"
|
||||
)
|
||||
|
||||
var (
|
||||
DISK_TYPES = []string{DISK_TYPE_ROTATE, DISK_TYPE_SSD, DISK_TYPE_HYBRID}
|
||||
STORAGE_LOCAL_TYPES = []string{STORAGE_LOCAL, STORAGE_BAREMETAL}
|
||||
STORAGE_SUPPORT_TYPES = STORAGE_LOCAL_TYPES
|
||||
STORAGE_ALL_TYPES = []string{
|
||||
STORAGE_LOCAL, STORAGE_BAREMETAL, STORAGE_SHEEPDOG,
|
||||
STORAGE_RBD, STORAGE_DOCKER, STORAGE_NAS, STORAGE_VSAN,
|
||||
STORAGE_NFS,
|
||||
}
|
||||
STORAGE_TYPES = []string{STORAGE_LOCAL, STORAGE_BAREMETAL, STORAGE_SHEEPDOG,
|
||||
STORAGE_RBD, STORAGE_DOCKER, STORAGE_NAS, STORAGE_VSAN, STORAGE_NFS,
|
||||
STORAGE_PUBLIC_CLOUD, STORAGE_CLOUD_SSD, STORAGE_CLOUD_ESSD, STORAGE_EPHEMERAL_SSD, STORAGE_CLOUD_EFFICIENCY,
|
||||
STORAGE_STANDARD_LRS, STORAGE_STANDARDSSD_LRS, STORAGE_PREMIUM_LRS,
|
||||
STORAGE_GP2_SSD, STORAGE_IO1_SSD, STORAGE_ST1_HDD, STORAGE_SC1_HDD, STORAGE_STANDARD_HDD,
|
||||
STORAGE_LOCAL_BASIC, STORAGE_LOCAL_SSD, STORAGE_CLOUD_BASIC, STORAGE_CLOUD_PREMIUM,
|
||||
STORAGE_HUAWEI_SSD, STORAGE_HUAWEI_SAS, STORAGE_HUAWEI_SATA,
|
||||
STORAGE_OPENSTACK_ISCSI, STORAGE_UCLOUD_SATA, STORAGE_UCLOUD_SSD,
|
||||
}
|
||||
|
||||
STORAGE_LIMITED_TYPES = []string{STORAGE_LOCAL, STORAGE_BAREMETAL, STORAGE_NAS, STORAGE_RBD, STORAGE_NFS}
|
||||
)
|
||||
@@ -0,0 +1 @@
|
||||
package apis // import "yunion.io/x/onecloud/pkg/apis"
|
||||
@@ -0,0 +1,82 @@
|
||||
package scheduler
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
type ScheduleBaseConfig struct {
|
||||
BestEffort bool `json:"best_effort"`
|
||||
SuggestionLimit int64 `json:"suggestion_limit"`
|
||||
SuggestionAll bool `json:"suggestion_all"`
|
||||
IgnoreFilters []string `json:"ignore_filters"`
|
||||
SessionId string `json:"session_id"`
|
||||
|
||||
// usedby test api
|
||||
RecordLog bool `json:"record_to_history"`
|
||||
Details bool `json:"details"`
|
||||
}
|
||||
|
||||
type ForGuest struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type GroupRelation struct {
|
||||
GroupId string `json:"group_id"`
|
||||
Strategy string `json:"strategy"`
|
||||
Scope string `json:"scope"`
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
*compute.ServerConfigs
|
||||
|
||||
Memory int `json:"vmem_size"`
|
||||
Ncpu int `json:"vcpu_count"`
|
||||
Name string `json:"name"`
|
||||
GuestStatus string `json:"guest_status"`
|
||||
|
||||
// HostId used by migrate
|
||||
HostId string `json:"host_id"`
|
||||
|
||||
// DEPRECATED
|
||||
Metadata map[string]string `json:"__meta__"`
|
||||
ForGuests []*ForGuest `json:"for_guests"`
|
||||
GroupRelations []*GroupRelation `json:"group_releations"`
|
||||
Groups interface{} `json:"groups"`
|
||||
Id string `json:"id"`
|
||||
}
|
||||
|
||||
// ScheduleInput used by scheduler sync-schedule/test/forecast api
|
||||
type ScheduleInput struct {
|
||||
apis.Meta
|
||||
|
||||
ScheduleBaseConfig
|
||||
|
||||
ServerConfig
|
||||
}
|
||||
|
||||
type CandidateDisk struct {
|
||||
Index int `json:"index"`
|
||||
StorageId string `json:"storage_id"`
|
||||
}
|
||||
|
||||
type CandidateResource struct {
|
||||
HostId string `json:"host_id"`
|
||||
Name string `json:"name"`
|
||||
Disks []*CandidateDisk `json:"disks"`
|
||||
|
||||
// used by backup schedule
|
||||
BackupCandidate *CandidateResource `json:"backup_candidate"`
|
||||
IsMaster bool `json:"is_master"`
|
||||
IsSlave bool `json:"is_slave"`
|
||||
|
||||
// Error means no candidate found, include reasons
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
type ScheduleOutput struct {
|
||||
apis.Meta
|
||||
|
||||
Candidates []*CandidateResource `json:"candidates"`
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package scheduler // import "yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
@@ -397,7 +397,16 @@ func (app *Application) ListenAndServeWithCleanup(addr string, onStop func()) {
|
||||
func (app *Application) ListenAndServeTLSWithCleanup(addr string, certFile, keyFile string, onStop func()) {
|
||||
s := app.initServer(addr)
|
||||
app.registerCleanShutdown(s, onStop)
|
||||
app.listenAndServe(s, certFile, keyFile)
|
||||
app.waitCleanShutdown()
|
||||
}
|
||||
|
||||
func (app *Application) ListenAndServeWithoutCleanup(addr, certFile, keyFile string) {
|
||||
s := app.initServer(addr)
|
||||
app.listenAndServe(s, certFile, keyFile)
|
||||
}
|
||||
|
||||
func (app *Application) listenAndServe(s *http.Server, certFile, keyFile string) {
|
||||
var err error
|
||||
if len(certFile) == 0 && len(keyFile) == 0 {
|
||||
err = s.ListenAndServe()
|
||||
@@ -407,7 +416,6 @@ func (app *Application) ListenAndServeTLSWithCleanup(addr string, certFile, keyF
|
||||
if err != nil && err != http.ErrServerClosed {
|
||||
log.Fatalf("ListAndServer fail: %s", err)
|
||||
}
|
||||
app.waitCleanShutdown()
|
||||
}
|
||||
|
||||
func isJsonContentType(r *http.Request) bool {
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"yunion.io/x/pkg/util/workqueue"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
o "yunion.io/x/onecloud/pkg/baremetal/options"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/profiles"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/pxe"
|
||||
@@ -1162,7 +1163,7 @@ func (s *SBaremetalServer) GetRootTemplateId() string {
|
||||
return id
|
||||
}
|
||||
|
||||
func (s *SBaremetalServer) GetDiskConfig() ([]*baremetal.BaremetalDiskConfig, error) {
|
||||
func (s *SBaremetalServer) GetDiskConfig() ([]*api.BaremetalDiskConfig, error) {
|
||||
layouts := make([]baremetal.Layout, 0)
|
||||
err := s.desc.Unmarshal(&layouts, "disk_config")
|
||||
if err != nil {
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon"
|
||||
)
|
||||
import common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
|
||||
type BaremetalOptions struct {
|
||||
cloudcommon.CommonOptions
|
||||
common_options.CommonOptions
|
||||
|
||||
ListenInterface string `help:"Master net interface of baremetal server" default:"br0"`
|
||||
AccessAddress string `help:"Management IP address of baremetal server, only need to use when multiple address bind to ListenInterface"`
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
o "yunion.io/x/onecloud/pkg/baremetal/options"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/types"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/util/dhcp"
|
||||
)
|
||||
@@ -165,7 +165,7 @@ func (h *DHCPHandler) fetchConfig() (*dhcp.ResponseConfig, error) {
|
||||
h.baremetalInstance = bmInstance
|
||||
ipmiNic := h.baremetalInstance.GetIPMINic(h.ClientMac)
|
||||
if ipmiNic != nil && ipmiNic.Mac == h.ClientMac.String() {
|
||||
err = h.baremetalInstance.InitAdminNetif(h.ClientMac, h.netConfig, types.NIC_TYPE_IPMI, models.NETWORK_TYPE_IPMI)
|
||||
err = h.baremetalInstance.InitAdminNetif(h.ClientMac, h.netConfig, types.NIC_TYPE_IPMI, api.NETWORK_TYPE_IPMI)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -215,7 +215,7 @@ func (h *DHCPHandler) findNetworkConf(filterUseIp bool) (*types.SNetworkConfig,
|
||||
func (h *DHCPHandler) findBaremetalsOfAnyMac(isBaremetal bool) (*modules.ListResult, error) {
|
||||
session := h.baremetalManager.GetClientSession()
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(models.HOST_TYPE_BAREMETAL), "host_type")
|
||||
params.Add(jsonutils.NewString(api.HOST_TYPE_BAREMETAL), "host_type")
|
||||
params.Add(jsonutils.NewString(h.ClientMac.String()), "any_mac")
|
||||
if isBaremetal {
|
||||
params.Add(jsonutils.JSONTrue, "is_baremetal")
|
||||
@@ -292,7 +292,7 @@ func (h *DHCPHandler) doInitBaremetalAdminNetif(desc jsonutils.JSONObject) error
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = h.baremetalInstance.InitAdminNetif(h.ClientMac, h.netConfig, types.NIC_TYPE_ADMIN, models.NETWORK_TYPE_PXE)
|
||||
err = h.baremetalInstance.InitAdminNetif(h.ClientMac, h.netConfig, types.NIC_TYPE_ADMIN, api.NETWORK_TYPE_PXE)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -117,8 +117,6 @@ func (s *Server) Serve() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//tftpSrv := tftp.NewServer(tftpHandler.ReadHandler, nil)
|
||||
//tftpSrv.SetTimeout(5 * time.Second)
|
||||
|
||||
log.Infof("DHCPServer Bind %s %d", s.DHCPAddress, s.DHCPPort)
|
||||
dhcpSrv, _, err := dhcp.NewDHCPServer2(s.DHCPAddress, s.DHCPPort, false)
|
||||
|
||||
@@ -106,10 +106,23 @@ func (h *TFTPHandler) transferLog(clientAddr net.Addr, path string, err error) {
|
||||
}
|
||||
|
||||
func (s *Server) serveTFTP(l net.PacketConn, handler *TFTPHandler) error {
|
||||
bindDial := func(network, addr string) (net.Conn, error) {
|
||||
localIp := l.LocalAddr().(*net.UDPAddr).IP
|
||||
remoteAddr, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return net.DialUDP("udp", &net.UDPAddr{
|
||||
IP: localIp,
|
||||
Port: 0, // random free port
|
||||
}, remoteAddr)
|
||||
}
|
||||
|
||||
ts := tftp.Server{
|
||||
Handler: handler.Handle,
|
||||
InfoLog: func(msg string) { log.Debugf("TFTP msg: %s", msg) },
|
||||
TransferLog: handler.transferLog,
|
||||
Dial: bindDial,
|
||||
}
|
||||
err := ts.Serve(l)
|
||||
if err != nil {
|
||||
|
||||
@@ -9,7 +9,8 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/baremetal/handler"
|
||||
o "yunion.io/x/onecloud/pkg/baremetal/options"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/tasks"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon"
|
||||
app_common "yunion.io/x/onecloud/pkg/cloudcommon/app"
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/service"
|
||||
)
|
||||
|
||||
@@ -22,13 +23,13 @@ func New() *BaremetalService {
|
||||
}
|
||||
|
||||
func (s *BaremetalService) StartService() {
|
||||
cloudcommon.ParseOptions(&o.Options, os.Args, "baremetal.conf", "baremetal")
|
||||
cloudcommon.InitAuth(&o.Options.CommonOptions, s.startAgent)
|
||||
common_options.ParseOptions(&o.Options, os.Args, "baremetal.conf", "baremetal")
|
||||
app_common.InitAuth(&o.Options.CommonOptions, s.startAgent)
|
||||
|
||||
app := cloudcommon.InitApp(&o.Options.CommonOptions, false)
|
||||
app := app_common.InitApp(&o.Options.CommonOptions, false)
|
||||
handler.InitHandlers(app)
|
||||
|
||||
cloudcommon.ServeForeverWithCleanup(app, &o.Options.CommonOptions, func() {
|
||||
app_common.ServeForeverWithCleanup(app, &o.Options.CommonOptions, func() {
|
||||
tasks.OnStop()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package drivers
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
|
||||
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/hpssactl"
|
||||
_ "yunion.io/x/onecloud/pkg/baremetal/utils/raid/megactl"
|
||||
@@ -28,7 +29,7 @@ func GetDrivers(term *ssh.Client) []raid.IRaidDriver {
|
||||
return ret
|
||||
}
|
||||
|
||||
func BuildRaid(driver raid.IRaidDriver, confs []*baremetal.BaremetalDiskConfig, adapterIdx int) error {
|
||||
func BuildRaid(driver raid.IRaidDriver, confs []*api.BaremetalDiskConfig, adapterIdx int) error {
|
||||
if err := driver.PreBuildRaid(confs, adapterIdx); err != nil {
|
||||
return fmt.Errorf("PreBuildRaid: %v", err)
|
||||
}
|
||||
@@ -48,7 +49,7 @@ func BuildRaid(driver raid.IRaidDriver, confs []*baremetal.BaremetalDiskConfig,
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildRaid(adapter raid.IRaidAdapter, confs []*baremetal.BaremetalDiskConfig) error {
|
||||
func buildRaid(adapter raid.IRaidAdapter, confs []*api.BaremetalDiskConfig) error {
|
||||
if err := adapter.PreBuildRaid(confs); err != nil {
|
||||
return fmt.Errorf("PreBuildRaid: %v", err)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
"yunion.io/x/onecloud/pkg/util/regutils2"
|
||||
@@ -105,7 +106,7 @@ func (adapter *HPSARaidAdaptor) GetIndex() int {
|
||||
return adapter.index
|
||||
}
|
||||
|
||||
func (adapter *HPSARaidAdaptor) PreBuildRaid(confs []*baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *HPSARaidAdaptor) PreBuildRaid(confs []*api.BaremetalDiskConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -163,7 +164,7 @@ func (adapter *HPSARaidAdaptor) GetDevices() []*baremetal.BaremetalStorage {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (adapter *HPSARaidAdaptor) conf2Params(conf *baremetal.BaremetalDiskConfig) []string {
|
||||
func (adapter *HPSARaidAdaptor) conf2Params(conf *api.BaremetalDiskConfig) []string {
|
||||
params := []string{}
|
||||
if conf.Direct != nil {
|
||||
if *(conf.Direct) {
|
||||
@@ -195,7 +196,7 @@ func (adapter *HPSARaidAdaptor) getLastArray() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (adapter *HPSARaidAdaptor) buildRaid(level string, devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *HPSARaidAdaptor) buildRaid(level string, devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
labels := []string{}
|
||||
for _, dev := range devs {
|
||||
labels = append(labels, fmt.Sprintf("%s", GetSpecString(dev)))
|
||||
@@ -235,19 +236,19 @@ func (adapter *HPSARaidAdaptor) buildRaid(level string, devs []*baremetal.Bareme
|
||||
return err
|
||||
}
|
||||
|
||||
func (adapter *HPSARaidAdaptor) BuildRaid0(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *HPSARaidAdaptor) BuildRaid0(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.buildRaid("0", devs, conf)
|
||||
}
|
||||
|
||||
func (adapter *HPSARaidAdaptor) BuildRaid1(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *HPSARaidAdaptor) BuildRaid1(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.buildRaid("1", devs, conf)
|
||||
}
|
||||
|
||||
func (adapter *HPSARaidAdaptor) BuildRaid5(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *HPSARaidAdaptor) BuildRaid5(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.buildRaid("5", devs, conf)
|
||||
}
|
||||
|
||||
func (adapter *HPSARaidAdaptor) BuildRaid10(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *HPSARaidAdaptor) BuildRaid10(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.buildRaid("10", devs, conf)
|
||||
}
|
||||
|
||||
@@ -256,7 +257,7 @@ func (adapter *HPSARaidAdaptor) BuildNoneRaid(devs []*baremetal.BaremetalStorage
|
||||
// WT|WB] [NORA|RA] [Direct|Cached] [CachedBadBBU|NoCachedBadBBU]
|
||||
useWT := true
|
||||
useDirect := true
|
||||
if err := adapter.buildRaid("0", []*baremetal.BaremetalStorage{d}, &baremetal.BaremetalDiskConfig{WT: &useWT, Direct: &useDirect}); err != nil {
|
||||
if err := adapter.buildRaid("0", []*baremetal.BaremetalStorage{d}, &api.BaremetalDiskConfig{WT: &useWT, Direct: &useDirect}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -354,7 +355,7 @@ func (r *HPSARaid) parsePhyDevs(lines []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *HPSARaid) PreBuildRaid(_ []*baremetal.BaremetalDiskConfig, _ int) error {
|
||||
func (r *HPSARaid) PreBuildRaid(_ []*api.BaremetalDiskConfig, _ int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package raid
|
||||
|
||||
import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
)
|
||||
|
||||
@@ -8,21 +9,21 @@ type IRaidDriver interface {
|
||||
ParsePhyDevs() error
|
||||
GetName() string
|
||||
GetAdapters() []IRaidAdapter
|
||||
PreBuildRaid(confs []*baremetal.BaremetalDiskConfig, adapterIdx int) error
|
||||
PreBuildRaid(confs []*api.BaremetalDiskConfig, adapterIdx int) error
|
||||
|
||||
CleanRaid() error
|
||||
}
|
||||
|
||||
type IRaidAdapter interface {
|
||||
GetIndex() int
|
||||
PreBuildRaid(confs []*baremetal.BaremetalDiskConfig) error
|
||||
PreBuildRaid(confs []*api.BaremetalDiskConfig) error
|
||||
GetLogicVolumes() ([]int, error)
|
||||
RemoveLogicVolumes() error
|
||||
GetDevices() []*baremetal.BaremetalStorage
|
||||
|
||||
BuildRaid0(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error
|
||||
BuildRaid1(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error
|
||||
BuildRaid5(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error
|
||||
BuildRaid10(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error
|
||||
BuildRaid0(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error
|
||||
BuildRaid1(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error
|
||||
BuildRaid5(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error
|
||||
BuildRaid10(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error
|
||||
BuildNoneRaid(devs []*baremetal.BaremetalStorage) error
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
raiddrivers "yunion.io/x/onecloud/pkg/baremetal/utils/raid"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
"yunion.io/x/onecloud/pkg/util/regutils2"
|
||||
@@ -225,12 +226,12 @@ func (adapter *MegaRaidAdaptor) parseLogicVolumes(lines []string) []int {
|
||||
return lvIdx
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) PreBuildRaid(confs []*baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) PreBuildRaid(confs []*api.BaremetalDiskConfig) error {
|
||||
adapter.clearJBODDisks()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) conf2ParamsStorcliSize(conf *baremetal.BaremetalDiskConfig) []string {
|
||||
func (adapter *MegaRaidAdaptor) conf2ParamsStorcliSize(conf *api.BaremetalDiskConfig) []string {
|
||||
params := []string{}
|
||||
szStr := []string{}
|
||||
if len(conf.Size) > 0 {
|
||||
@@ -242,7 +243,7 @@ func (adapter *MegaRaidAdaptor) conf2ParamsStorcliSize(conf *baremetal.Baremetal
|
||||
return params
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) conf2ParamsStorcli(conf *baremetal.BaremetalDiskConfig) []string {
|
||||
func (adapter *MegaRaidAdaptor) conf2ParamsStorcli(conf *api.BaremetalDiskConfig) []string {
|
||||
params := []string{}
|
||||
if conf.WT != nil {
|
||||
if *conf.WT {
|
||||
@@ -278,7 +279,7 @@ func (adapter *MegaRaidAdaptor) conf2ParamsStorcli(conf *baremetal.BaremetalDisk
|
||||
return params
|
||||
}
|
||||
|
||||
func conf2Params(conf *baremetal.BaremetalDiskConfig) []string {
|
||||
func conf2Params(conf *api.BaremetalDiskConfig) []string {
|
||||
params := []string{}
|
||||
if conf.WT != nil {
|
||||
if *conf.WT {
|
||||
@@ -319,35 +320,35 @@ func conf2Params(conf *baremetal.BaremetalDiskConfig) []string {
|
||||
return params
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildRaid0(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildRaid0(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.storcliBuildRaid(devs, conf, 0)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildRaid0(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildRaid0(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.megacliBuildRaid(devs, conf, 0)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildRaid1(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildRaid1(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.storcliBuildRaid(devs, conf, 1)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildRaid1(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildRaid1(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.megacliBuildRaid(devs, conf, 1)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildRaid5(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildRaid5(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.storcliBuildRaid(devs, conf, 5)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildRaid5(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildRaid5(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.megacliBuildRaid(devs, conf, 5)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildRaid10(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildRaid10(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.storcliBuildRaid(devs, conf, 10)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildRaid10(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildRaid10(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
if len(devs)%2 != 0 {
|
||||
return fmt.Errorf("Odd number of %d devs", len(devs))
|
||||
}
|
||||
@@ -367,7 +368,7 @@ func (adapter *MegaRaidAdaptor) megacliBuildRaid10(devs []*baremetal.BaremetalSt
|
||||
return err
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildRaid(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig, level uint) error {
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildRaid(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig, level uint) error {
|
||||
args := []string{}
|
||||
args = append(args, fmt.Sprintf("/c%d", adapter.index))
|
||||
args = append(args, "add", "vd", fmt.Sprintf("type=r%d", level))
|
||||
@@ -387,7 +388,7 @@ func (adapter *MegaRaidAdaptor) storcliBuildRaid(devs []*baremetal.BaremetalStor
|
||||
return err
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildRaid(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig, level uint) error {
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildRaid(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig, level uint) error {
|
||||
labels := []string{}
|
||||
for _, dev := range devs {
|
||||
labels = append(labels, GetSpecString(dev))
|
||||
@@ -403,8 +404,8 @@ func (adapter *MegaRaidAdaptor) megacliBuildRaid(devs []*baremetal.BaremetalStor
|
||||
|
||||
func cliBuildRaid(
|
||||
devs []*baremetal.BaremetalStorage,
|
||||
conf *baremetal.BaremetalDiskConfig,
|
||||
funcs ...func([]*baremetal.BaremetalStorage, *baremetal.BaremetalDiskConfig) error,
|
||||
conf *api.BaremetalDiskConfig,
|
||||
funcs ...func([]*baremetal.BaremetalStorage, *api.BaremetalDiskConfig) error,
|
||||
) error {
|
||||
var err error
|
||||
for _, f := range funcs {
|
||||
@@ -416,19 +417,19 @@ func cliBuildRaid(
|
||||
return err
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) BuildRaid0(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) BuildRaid0(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return cliBuildRaid(devs, conf, adapter.megacliBuildRaid0, adapter.storcliBuildRaid0)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) BuildRaid1(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) BuildRaid1(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return cliBuildRaid(devs, conf, adapter.megacliBuildRaid1, adapter.storcliBuildRaid1)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) BuildRaid5(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) BuildRaid5(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return cliBuildRaid(devs, conf, adapter.megacliBuildRaid5, adapter.storcliBuildRaid5)
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) BuildRaid10(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) BuildRaid10(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return cliBuildRaid(devs, conf, adapter.megacliBuildRaid10, adapter.storcliBuildRaid10)
|
||||
}
|
||||
|
||||
@@ -492,7 +493,7 @@ func (adapter *MegaRaidAdaptor) storcliBuildJBOD(devs []*baremetal.BaremetalStor
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildNoRaid(devs []*baremetal.BaremetalStorage, _ *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) storcliBuildNoRaid(devs []*baremetal.BaremetalStorage, _ *api.BaremetalDiskConfig) error {
|
||||
err := adapter.storcliBuildJBOD(devs)
|
||||
if err == nil {
|
||||
return nil
|
||||
@@ -513,7 +514,7 @@ func (adapter *MegaRaidAdaptor) storcliBuildNoRaid(devs []*baremetal.BaremetalSt
|
||||
return err
|
||||
}
|
||||
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildNoRaid(devs []*baremetal.BaremetalStorage, _ *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MegaRaidAdaptor) megacliBuildNoRaid(devs []*baremetal.BaremetalStorage, _ *api.BaremetalDiskConfig) error {
|
||||
err := adapter.megacliBuildJBOD(devs)
|
||||
if err == nil {
|
||||
return nil
|
||||
@@ -746,7 +747,7 @@ func (raid *MegaRaid) CleanRaid() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (raid *MegaRaid) PreBuildRaid(_ []*baremetal.BaremetalDiskConfig, _ int) error {
|
||||
func (raid *MegaRaid) PreBuildRaid(_ []*api.BaremetalDiskConfig, _ int) error {
|
||||
return raid.clearForeignState()
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
"yunion.io/x/onecloud/pkg/util/ssh"
|
||||
@@ -185,11 +186,11 @@ func (adapter *MarvelRaidAdaptor) removeLogicVolume(idx int) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (adapter *MarvelRaidAdaptor) PreBuildRaid(confs []*baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MarvelRaidAdaptor) PreBuildRaid(confs []*api.BaremetalDiskConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adapter *MarvelRaidAdaptor) buildRaid(level string, devs []*baremetal.BaremetalStorage, _ *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MarvelRaidAdaptor) buildRaid(level string, devs []*baremetal.BaremetalStorage, _ *api.BaremetalDiskConfig) error {
|
||||
pds := []string{}
|
||||
for _, dev := range devs {
|
||||
pds = append(pds, fmt.Sprintf("%s", GetSpecString(dev)))
|
||||
@@ -200,20 +201,20 @@ func (adapter *MarvelRaidAdaptor) buildRaid(level string, devs []*baremetal.Bare
|
||||
return err
|
||||
}
|
||||
|
||||
func (adapter *MarvelRaidAdaptor) BuildRaid0(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MarvelRaidAdaptor) BuildRaid0(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.buildRaid("-r0", devs, conf)
|
||||
}
|
||||
|
||||
func (adapter *MarvelRaidAdaptor) BuildRaid1(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MarvelRaidAdaptor) BuildRaid1(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.buildRaid("-r1", devs, conf)
|
||||
}
|
||||
|
||||
func (adapter *MarvelRaidAdaptor) BuildRaid5(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MarvelRaidAdaptor) BuildRaid5(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
//return adapter.buildRaid("-r5", devs, conf)
|
||||
return fmt.Errorf("BuildRaid5 not impl")
|
||||
}
|
||||
|
||||
func (adapter *MarvelRaidAdaptor) BuildRaid10(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *MarvelRaidAdaptor) BuildRaid10(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.buildRaid("-r10", devs, conf)
|
||||
}
|
||||
|
||||
@@ -276,7 +277,7 @@ func (r *MarvelRaid) parseAdapters(lines []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *MarvelRaid) PreBuildRaid(_ []*baremetal.BaremetalDiskConfig, _ int) error {
|
||||
func (r *MarvelRaid) PreBuildRaid(_ []*api.BaremetalDiskConfig, _ int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/baremetal/utils/raid"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
"yunion.io/x/onecloud/pkg/util/ssh"
|
||||
@@ -225,11 +226,11 @@ func (adapter *Mpt2SASRaidAdaptor) setBootIR() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adapter *Mpt2SASRaidAdaptor) PreBuildRaid(confs []*baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *Mpt2SASRaidAdaptor) PreBuildRaid(confs []*api.BaremetalDiskConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adapter *Mpt2SASRaidAdaptor) buildRaid(level string, devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *Mpt2SASRaidAdaptor) buildRaid(level string, devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
if len(conf.Size) > 1 {
|
||||
return fmt.Errorf("Subdivide sub-size not supported")
|
||||
}
|
||||
@@ -253,19 +254,19 @@ func (adapter *Mpt2SASRaidAdaptor) buildRaid(level string, devs []*baremetal.Bar
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adapter *Mpt2SASRaidAdaptor) BuildRaid0(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *Mpt2SASRaidAdaptor) BuildRaid0(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.buildRaid("RAID0", devs, conf)
|
||||
}
|
||||
|
||||
func (adapter *Mpt2SASRaidAdaptor) BuildRaid1(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *Mpt2SASRaidAdaptor) BuildRaid1(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return adapter.buildRaid("RAID1", devs, conf)
|
||||
}
|
||||
|
||||
func (adapter *Mpt2SASRaidAdaptor) BuildRaid5(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *Mpt2SASRaidAdaptor) BuildRaid5(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
return fmt.Errorf("Not impl")
|
||||
}
|
||||
|
||||
func (adapter *Mpt2SASRaidAdaptor) BuildRaid10(devs []*baremetal.BaremetalStorage, conf *baremetal.BaremetalDiskConfig) error {
|
||||
func (adapter *Mpt2SASRaidAdaptor) BuildRaid10(devs []*baremetal.BaremetalStorage, conf *api.BaremetalDiskConfig) error {
|
||||
if len(devs) > 10 {
|
||||
return fmt.Errorf("RAID10 supports no more than 10 disks")
|
||||
}
|
||||
@@ -342,7 +343,7 @@ func (r *Mpt2SASRaid) GetCommand(args ...string) string {
|
||||
return raid.GetCommand(r.utility, args...)
|
||||
}
|
||||
|
||||
func (r *Mpt2SASRaid) PreBuildRaid(_ []*baremetal.BaremetalDiskConfig, _ int) error {
|
||||
func (r *Mpt2SASRaid) PreBuildRaid(_ []*api.BaremetalDiskConfig, _ int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cloudcommon
|
||||
package app
|
||||
|
||||
import (
|
||||
"net"
|
||||
@@ -8,10 +8,11 @@ import (
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
"yunion.io/x/onecloud/pkg/util/seclib2"
|
||||
)
|
||||
|
||||
func InitApp(options *CommonOptions, dbAccess bool) *appsrv.Application {
|
||||
func InitApp(options *common_options.CommonOptions, dbAccess bool) *appsrv.Application {
|
||||
// cache := appsrv.NewCache(options.AuthTokenCacheSize)
|
||||
app := appsrv.NewApplication(options.ApplicationID, options.RequestWorkerCount, dbAccess)
|
||||
app.CORSAllowHosts(options.CorsHosts)
|
||||
@@ -23,12 +24,11 @@ func InitApp(options *CommonOptions, dbAccess bool) *appsrv.Application {
|
||||
return app
|
||||
}
|
||||
|
||||
func ServeForever(app *appsrv.Application, options *CommonOptions) {
|
||||
func ServeForever(app *appsrv.Application, options *common_options.CommonOptions) {
|
||||
ServeForeverWithCleanup(app, options, nil)
|
||||
}
|
||||
|
||||
func ServeForeverWithCleanup(app *appsrv.Application, options *CommonOptions, onStop func()) {
|
||||
AppDBInit(app)
|
||||
func ServeForeverWithCleanup(app *appsrv.Application, options *common_options.CommonOptions, onStop func()) {
|
||||
addr := net.JoinHostPort(options.Address, strconv.Itoa(options.Port))
|
||||
proto := "http"
|
||||
if options.EnableSsl {
|
||||
@@ -1,4 +1,4 @@
|
||||
package cloudcommon
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -7,11 +7,12 @@ import (
|
||||
"time"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
)
|
||||
|
||||
func InitAuth(options *CommonOptions, authComplete auth.AuthCompletedCallback) {
|
||||
func InitAuth(options *common_options.CommonOptions, authComplete auth.AuthCompletedCallback) {
|
||||
|
||||
if len(options.AuthURL) == 0 {
|
||||
fmt.Println("Missing AuthURL")
|
||||
@@ -0,0 +1 @@
|
||||
package app // import "yunion.io/x/onecloud/pkg/cloudcommon/app"
|
||||
@@ -0,0 +1 @@
|
||||
package cmdline // import "yunion.io/x/onecloud/pkg/cloudcommon/cmdline"
|
||||
@@ -0,0 +1,406 @@
|
||||
package cmdline
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/util/fileutils"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
)
|
||||
|
||||
type resourceConfigOutput struct {
|
||||
keyword string
|
||||
keywordPlural string
|
||||
}
|
||||
|
||||
func newResouceConfigOutput(kw, kws string) *resourceConfigOutput {
|
||||
return &resourceConfigOutput{keyword: kw, keywordPlural: kws}
|
||||
}
|
||||
|
||||
func (o resourceConfigOutput) Keyword() string {
|
||||
return o.keyword
|
||||
}
|
||||
|
||||
func (o resourceConfigOutput) KeywordPlural() string {
|
||||
return o.keywordPlural
|
||||
}
|
||||
|
||||
type iResourcesOutput interface {
|
||||
Keyword() string
|
||||
KeywordPlural() string
|
||||
NewConfig() interface{}
|
||||
ParseDesc(desc string, idx int) (interface{}, error)
|
||||
Add(config interface{})
|
||||
Resources() interface{}
|
||||
}
|
||||
|
||||
func fetchResourceConfigsByJSON(
|
||||
obj jsonutils.JSONObject,
|
||||
output iResourcesOutput,
|
||||
) error {
|
||||
if obj == nil {
|
||||
obj = jsonutils.NewDict()
|
||||
}
|
||||
keywordPlural := output.KeywordPlural()
|
||||
keyword := output.Keyword()
|
||||
if obj.Contains(keywordPlural) {
|
||||
err := obj.Unmarshal(output.Resources(), keywordPlural)
|
||||
return err
|
||||
}
|
||||
|
||||
configs := jsonutils.GetArrayOfPrefix(obj, keyword)
|
||||
for idx, config := range configs {
|
||||
configJson, ok := config.(*jsonutils.JSONDict)
|
||||
resConfig := output.NewConfig()
|
||||
if ok {
|
||||
if err := configJson.Unmarshal(resConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
configStr, err := config.GetString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resConfig, err = output.ParseDesc(configStr, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
output.Add(resConfig)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type diskConfigOutput struct {
|
||||
*resourceConfigOutput
|
||||
disks []*compute.DiskConfig
|
||||
}
|
||||
|
||||
func newDiskConfigOutput() *diskConfigOutput {
|
||||
return &diskConfigOutput{
|
||||
resourceConfigOutput: newResouceConfigOutput("disk", "disks"),
|
||||
}
|
||||
}
|
||||
|
||||
func (output *diskConfigOutput) Disks() []*compute.DiskConfig {
|
||||
return output.disks
|
||||
}
|
||||
|
||||
func (output *diskConfigOutput) Resources() interface{} {
|
||||
return &output.disks
|
||||
}
|
||||
|
||||
func (output *diskConfigOutput) NewConfig() interface{} {
|
||||
return new(compute.DiskConfig)
|
||||
}
|
||||
|
||||
func (output *diskConfigOutput) Add(config interface{}) {
|
||||
output.disks = append(output.disks, config.(*compute.DiskConfig))
|
||||
}
|
||||
|
||||
func (output *diskConfigOutput) ParseDesc(desc string, idx int) (interface{}, error) {
|
||||
return ParseDiskConfig(desc, idx)
|
||||
}
|
||||
|
||||
func FetchDiskConfigsByJSON(obj jsonutils.JSONObject) ([]*compute.DiskConfig, error) {
|
||||
output := newDiskConfigOutput()
|
||||
err := fetchResourceConfigsByJSON(obj, output)
|
||||
return output.Disks(), err
|
||||
}
|
||||
|
||||
type netConfigOutput struct {
|
||||
*resourceConfigOutput
|
||||
nets []*compute.NetworkConfig
|
||||
}
|
||||
|
||||
func newNetworkConfigOutput() *netConfigOutput {
|
||||
return &netConfigOutput{
|
||||
resourceConfigOutput: newResouceConfigOutput("net", "nets"),
|
||||
}
|
||||
}
|
||||
|
||||
func (output *netConfigOutput) Networks() []*compute.NetworkConfig {
|
||||
return output.nets
|
||||
}
|
||||
|
||||
func (output *netConfigOutput) Resources() interface{} {
|
||||
return &output.nets
|
||||
}
|
||||
|
||||
func (output *netConfigOutput) NewConfig() interface{} {
|
||||
return new(compute.NetworkConfig)
|
||||
}
|
||||
|
||||
func (output *netConfigOutput) Add(config interface{}) {
|
||||
output.nets = append(output.nets, config.(*compute.NetworkConfig))
|
||||
}
|
||||
|
||||
func (output *netConfigOutput) ParseDesc(desc string, idx int) (interface{}, error) {
|
||||
return ParseNetworkConfig(desc, idx)
|
||||
}
|
||||
|
||||
func FetchNetworkConfigsByJSON(obj jsonutils.JSONObject) ([]*compute.NetworkConfig, error) {
|
||||
output := newNetworkConfigOutput()
|
||||
err := fetchResourceConfigsByJSON(obj, output)
|
||||
return output.Networks(), err
|
||||
}
|
||||
|
||||
type schedtagConfigOutput struct {
|
||||
*resourceConfigOutput
|
||||
tags []*compute.SchedtagConfig
|
||||
}
|
||||
|
||||
func newSchedtagConfigOutput() *schedtagConfigOutput {
|
||||
return &schedtagConfigOutput{
|
||||
resourceConfigOutput: newResouceConfigOutput("schedtag", "schedtags"),
|
||||
}
|
||||
}
|
||||
|
||||
func (output *schedtagConfigOutput) Schedtags() []*compute.SchedtagConfig {
|
||||
return output.tags
|
||||
}
|
||||
|
||||
func (output *schedtagConfigOutput) Resources() interface{} {
|
||||
return &output.tags
|
||||
}
|
||||
|
||||
func (output *schedtagConfigOutput) NewConfig() interface{} {
|
||||
return new(compute.SchedtagConfig)
|
||||
}
|
||||
|
||||
func (output *schedtagConfigOutput) Add(config interface{}) {
|
||||
output.tags = append(output.tags, config.(*compute.SchedtagConfig))
|
||||
}
|
||||
|
||||
func (output *schedtagConfigOutput) ParseDesc(desc string, _ int) (interface{}, error) {
|
||||
return ParseSchedtagConfig(desc)
|
||||
}
|
||||
|
||||
func FetchSchedtagConfigsByJSON(obj jsonutils.JSONObject) ([]*compute.SchedtagConfig, error) {
|
||||
output := newSchedtagConfigOutput()
|
||||
if err := fetchResourceConfigsByJSON(obj, output); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(output.tags) == 0 {
|
||||
// compatible with old api
|
||||
schedtags, _ := obj.GetMap("aggregate_strategy")
|
||||
if schedtags != nil {
|
||||
for id, strategyObj := range schedtags {
|
||||
strategy, _ := strategyObj.GetString()
|
||||
output.tags = append(output.tags, &compute.SchedtagConfig{
|
||||
Id: id,
|
||||
Strategy: strategy,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return output.tags, nil
|
||||
}
|
||||
|
||||
type isoDevConfigOutput struct {
|
||||
*resourceConfigOutput
|
||||
devs []*compute.IsolatedDeviceConfig
|
||||
}
|
||||
|
||||
func newIsoDevConfigOutput() *isoDevConfigOutput {
|
||||
return &isoDevConfigOutput{
|
||||
resourceConfigOutput: newResouceConfigOutput("isolated_device", "isolated_devices"),
|
||||
}
|
||||
}
|
||||
|
||||
func (output *isoDevConfigOutput) Devs() []*compute.IsolatedDeviceConfig {
|
||||
return output.devs
|
||||
}
|
||||
|
||||
func (output *isoDevConfigOutput) Resources() interface{} {
|
||||
return &output.devs
|
||||
}
|
||||
|
||||
func (output *isoDevConfigOutput) NewConfig() interface{} {
|
||||
return new(compute.IsolatedDeviceConfig)
|
||||
}
|
||||
|
||||
func (output *isoDevConfigOutput) Add(config interface{}) {
|
||||
output.devs = append(output.devs, config.(*compute.IsolatedDeviceConfig))
|
||||
}
|
||||
|
||||
func (output *isoDevConfigOutput) ParseDesc(desc string, idx int) (interface{}, error) {
|
||||
return ParseIsolatedDevice(desc, idx)
|
||||
}
|
||||
|
||||
func FetchIsolatedDeviceConfigsByJSON(obj jsonutils.JSONObject) ([]*compute.IsolatedDeviceConfig, error) {
|
||||
output := newIsoDevConfigOutput()
|
||||
err := fetchResourceConfigsByJSON(obj, output)
|
||||
return output.devs, err
|
||||
}
|
||||
|
||||
type bmDiskConfigOutput struct {
|
||||
*resourceConfigOutput
|
||||
configs []*compute.BaremetalDiskConfig
|
||||
}
|
||||
|
||||
func newbmDiskConfigOutput() *bmDiskConfigOutput {
|
||||
return &bmDiskConfigOutput{
|
||||
resourceConfigOutput: newResouceConfigOutput("baremetal_disk_config", "baremetal_disk_configs"),
|
||||
}
|
||||
}
|
||||
|
||||
func (output *bmDiskConfigOutput) Devs() []*compute.BaremetalDiskConfig {
|
||||
return output.configs
|
||||
}
|
||||
|
||||
func (output *bmDiskConfigOutput) Resources() interface{} {
|
||||
return &output.configs
|
||||
}
|
||||
|
||||
func (output *bmDiskConfigOutput) NewConfig() interface{} {
|
||||
return new(compute.BaremetalDiskConfig)
|
||||
}
|
||||
|
||||
func (output *bmDiskConfigOutput) Add(config interface{}) {
|
||||
output.configs = append(output.configs, config.(*compute.BaremetalDiskConfig))
|
||||
}
|
||||
|
||||
func (output *bmDiskConfigOutput) ParseDesc(desc string, idx int) (interface{}, error) {
|
||||
return ParseBaremetalDiskConfig(desc)
|
||||
}
|
||||
|
||||
func FetchBaremetalDiskConfigsByJSON(obj jsonutils.JSONObject) ([]*compute.BaremetalDiskConfig, error) {
|
||||
output := newbmDiskConfigOutput()
|
||||
err := fetchResourceConfigsByJSON(obj, output)
|
||||
return output.configs, err
|
||||
}
|
||||
|
||||
func FetchServerConfigsByJSON(obj jsonutils.JSONObject) (*compute.ServerConfigs, error) {
|
||||
conf := new(compute.ServerConfigs)
|
||||
if err := obj.Unmarshal(conf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var err error
|
||||
conf.Disks, err = FetchDiskConfigsByJSON(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conf.Networks, err = FetchNetworkConfigsByJSON(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conf.Schedtags, err = FetchSchedtagConfigsByJSON(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conf.IsolatedDevices, err = FetchIsolatedDeviceConfigsByJSON(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conf.BaremetalDiskConfigs, err = FetchBaremetalDiskConfigsByJSON(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
func FetchScheduleInputByJSON(obj jsonutils.JSONObject) (*scheduler.ScheduleInput, error) {
|
||||
input := new(scheduler.ScheduleInput)
|
||||
err := obj.Unmarshal(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conf := &input.ServerConfig
|
||||
conf.ServerConfigs, err = FetchServerConfigsByJSON(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func FetchDeployConfigsByJSON(obj jsonutils.JSONObject) ([]*compute.DeployConfig, error) {
|
||||
deploys := make([]*compute.DeployConfig, 0)
|
||||
if obj.Contains("deploy_configs") {
|
||||
err := obj.Unmarshal(&deploys, "deploy_configs")
|
||||
return deploys, err
|
||||
}
|
||||
for idx := 0; obj.Contains(fmt.Sprintf("deploy.%d.path", idx)); idx += 1 {
|
||||
path, _ := obj.GetString(fmt.Sprintf("deploy.%d.path", idx))
|
||||
action, _ := obj.GetString(fmt.Sprintf("deploy.%d.action", idx))
|
||||
content, _ := obj.GetString(fmt.Sprintf("deploy.%d.content", idx))
|
||||
deploys = append(deploys, &compute.DeployConfig{Path: path, Action: action, Content: content})
|
||||
}
|
||||
return deploys, nil
|
||||
}
|
||||
|
||||
func FetchServerCreateInputByJSON(obj jsonutils.JSONObject) (*compute.ServerCreateInput, error) {
|
||||
input := new(compute.ServerCreateInput)
|
||||
// compatible with vmem_size string
|
||||
memSizeObj, _ := obj.Get("vmem_size")
|
||||
if memSizeObj != nil {
|
||||
if _, ok := memSizeObj.(*jsonutils.JSONString); ok {
|
||||
memStr, err := memSizeObj.GetString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !regutils.MatchSize(memStr) {
|
||||
return nil, fmt.Errorf("Invalid memory size string: %s, Memory size must be number[+unit], like 256M, 1G or 256", memStr)
|
||||
}
|
||||
vmemSize, err := fileutils.GetSizeMb(memStr, 'M', 1024)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
obj.(*jsonutils.JSONDict).Set("vmem_size", jsonutils.NewInt(int64(vmemSize)))
|
||||
}
|
||||
}
|
||||
|
||||
err := obj.Unmarshal(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config, err := FetchServerConfigsByJSON(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
input.ServerConfigs = config
|
||||
|
||||
deployConfigs, err := FetchDeployConfigsByJSON(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
input.DeployConfigs = deployConfigs
|
||||
|
||||
if skuName := jsonutils.GetAnyString(obj, []string{"sku", "flavor", "instance_type"}); skuName != "" {
|
||||
input.InstanceType = skuName
|
||||
}
|
||||
if keypair := jsonutils.GetAnyString(obj, []string{"keypair", "keypair_id"}); keypair != "" {
|
||||
input.Keypair = keypair
|
||||
}
|
||||
if secgroup := jsonutils.GetAnyString(obj, []string{"secgroup", "secgroup_id", "secgrp_id"}); len(secgroup) != 0 {
|
||||
input.Secgroup = secgroup
|
||||
}
|
||||
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func FetchDiskCreateInputByJSON(data jsonutils.JSONObject) (*compute.DiskCreateInput, error) {
|
||||
config := new(compute.DiskConfig)
|
||||
input := &compute.DiskCreateInput{
|
||||
DiskConfig: config,
|
||||
}
|
||||
if err := data.Unmarshal(input); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if data.Contains("disk") {
|
||||
desc, err := data.GetString("disk")
|
||||
config, err = ParseDiskConfig(desc, -1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
input.DiskConfig = config
|
||||
}
|
||||
if storageId := jsonutils.GetAnyString(data, []string{"storage_id", "storage"}); storageId != "" {
|
||||
input.Storage = storageId
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package cmdline
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
func TestFetchServerConfigsByJSON(t *testing.T) {
|
||||
type args struct {
|
||||
obj jsonutils.JSONObject
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *compute.ServerConfigs
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "all configs",
|
||||
args: args{jsonutils.Marshal(map[string]string{
|
||||
"disk.0": "1g:centos",
|
||||
"net.0": "192.168.222.3:inf0",
|
||||
"schedtag.0": "ssd:require",
|
||||
"schedtag.1": "container:exclude",
|
||||
"isolated_device.0": "vendor=nvidia:p400",
|
||||
"baremetal_disk_config.0": "raid0:[1,2]",
|
||||
})},
|
||||
want: &compute.ServerConfigs{
|
||||
Disks: []*compute.DiskConfig{
|
||||
{
|
||||
Index: 0,
|
||||
SizeMb: 1024,
|
||||
ImageId: "centos",
|
||||
Medium: "hybrid",
|
||||
},
|
||||
},
|
||||
Networks: []*compute.NetworkConfig{
|
||||
{
|
||||
Network: "inf0",
|
||||
Address: "192.168.222.3",
|
||||
},
|
||||
},
|
||||
Schedtags: []*compute.SchedtagConfig{
|
||||
{
|
||||
Id: "ssd",
|
||||
Strategy: "require",
|
||||
},
|
||||
{
|
||||
Id: "container",
|
||||
Strategy: "exclude",
|
||||
},
|
||||
},
|
||||
IsolatedDevices: []*compute.IsolatedDeviceConfig{
|
||||
{
|
||||
Vendor: "nvidia",
|
||||
Model: "p400",
|
||||
},
|
||||
},
|
||||
BaremetalDiskConfigs: []*compute.BaremetalDiskConfig{
|
||||
{
|
||||
Type: "hybrid",
|
||||
Conf: "raid0",
|
||||
Range: []int64{1, 2},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := FetchServerConfigsByJSON(tt.args.obj)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("FetchServerConfigsByJSON() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
gotJ := jsonutils.Marshal(got).String()
|
||||
wantJ := jsonutils.Marshal(tt.want).String()
|
||||
if !reflect.DeepEqual(gotJ, wantJ) {
|
||||
t.Errorf("FetchServerConfigsByJSON() = %v, want %v", gotJ, wantJ)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,349 @@
|
||||
package cmdline
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/util/fileutils"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/util/osprofile"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
"yunion.io/x/pkg/util/sets"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrorEmptyDesc = errors.New("Empty description")
|
||||
)
|
||||
|
||||
// ParseSchedtagConfig desc format: <schedtagName>:<strategy>
|
||||
func ParseSchedtagConfig(desc string) (*compute.SchedtagConfig, error) {
|
||||
if len(desc) == 0 {
|
||||
return nil, ErrorEmptyDesc
|
||||
}
|
||||
parts := strings.Split(desc, ":")
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("Invalid desc: %s", desc)
|
||||
}
|
||||
strategy := parts[1]
|
||||
if !utils.IsInStringArray(strategy, compute.STRATEGY_LIST) {
|
||||
return nil, fmt.Errorf("Invalid strategy: %s", strategy)
|
||||
}
|
||||
return &compute.SchedtagConfig{
|
||||
Id: parts[0],
|
||||
Strategy: parts[1],
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ParseResourceSchedtagConfig desc format: <idx>:<schedtagName>:<strategy>
|
||||
func ParseResourceSchedtagConfig(desc string) (int, *compute.SchedtagConfig, error) {
|
||||
if len(desc) == 0 {
|
||||
return 0, nil, ErrorEmptyDesc
|
||||
}
|
||||
parts := strings.Split(desc, ":")
|
||||
if len(parts) != 3 {
|
||||
return 0, nil, fmt.Errorf("Invalid desc: %s", desc)
|
||||
}
|
||||
idx, err := strconv.Atoi(parts[0])
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
tag, err := ParseSchedtagConfig(fmt.Sprintf("%s:%s", parts[1], parts[2]))
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return idx, tag, nil
|
||||
}
|
||||
|
||||
func ParseDiskConfig(diskStr string, idx int) (*compute.DiskConfig, error) {
|
||||
if len(diskStr) == 0 {
|
||||
return nil, ErrorEmptyDesc
|
||||
}
|
||||
diskConfig := new(compute.DiskConfig)
|
||||
diskConfig.Index = idx
|
||||
|
||||
// default backend and medium type
|
||||
diskConfig.Backend = "" // STORAGE_LOCAL
|
||||
diskConfig.Medium = compute.DISK_TYPE_HYBRID
|
||||
|
||||
parts := strings.Split(diskStr, ":")
|
||||
for _, p := range parts {
|
||||
if len(p) == 0 {
|
||||
continue
|
||||
}
|
||||
if regutils.MatchSize(p) {
|
||||
diskConfig.SizeMb, _ = fileutils.GetSizeMb(p, 'M', 1024)
|
||||
} else if utils.IsInStringArray(p, osprofile.FS_TYPES) {
|
||||
diskConfig.Fs = p
|
||||
} else if utils.IsInStringArray(p, osprofile.IMAGE_FORMAT_TYPES) {
|
||||
diskConfig.Format = p
|
||||
} else if utils.IsInStringArray(p, osprofile.DISK_DRIVERS) {
|
||||
diskConfig.Driver = p
|
||||
} else if utils.IsInStringArray(p, osprofile.DISK_CACHE_MODES) {
|
||||
diskConfig.Cache = p
|
||||
} else if utils.IsInStringArray(p, compute.DISK_TYPES) {
|
||||
diskConfig.Medium = p
|
||||
} else if utils.IsInStringArray(p, []string{compute.DISK_TYPE_VOLUME}) {
|
||||
diskConfig.DiskType = p
|
||||
} else if p[0] == '/' {
|
||||
diskConfig.Mountpoint = p
|
||||
} else if p == "autoextend" {
|
||||
diskConfig.SizeMb = -1
|
||||
} else if strings.HasPrefix(p, "snapshot-") {
|
||||
// HACK: use snapshot creat disk format snapshot-id
|
||||
// example: snapshot-3140cecb-ccc4-4865-abae-3a5ba8c69d9b
|
||||
diskConfig.SnapshotId = p[len("snapshot-"):]
|
||||
} else if len(p) > 0 {
|
||||
diskConfig.ImageId = p
|
||||
}
|
||||
}
|
||||
|
||||
return diskConfig, nil
|
||||
}
|
||||
|
||||
func ParseNetworkConfigByJSON(desc jsonutils.JSONObject, idx int) (*compute.NetworkConfig, error) {
|
||||
if _, ok := desc.(*jsonutils.JSONString); ok {
|
||||
descStr, _ := desc.GetString()
|
||||
return ParseNetworkConfig(descStr, idx)
|
||||
}
|
||||
conf := new(compute.NetworkConfig)
|
||||
conf.Index = idx
|
||||
err := desc.Unmarshal(conf)
|
||||
return conf, err
|
||||
}
|
||||
|
||||
func ParseNetworkConfig(desc string, idx int) (*compute.NetworkConfig, error) {
|
||||
if len(desc) == 0 {
|
||||
return nil, ErrorEmptyDesc
|
||||
}
|
||||
parts := strings.Split(desc, ":")
|
||||
netConfig := new(compute.NetworkConfig)
|
||||
netConfig.Index = idx
|
||||
for _, p := range parts {
|
||||
if len(p) == 0 {
|
||||
continue
|
||||
}
|
||||
if regutils.MatchIP4Addr(p) {
|
||||
netConfig.Address = p
|
||||
} else if regutils.MatchIP6Addr(p) {
|
||||
netConfig.Address6 = p
|
||||
} else if regutils.MatchCompactMacAddr(p) {
|
||||
netConfig.Mac = netutils.MacUnpackHex(p)
|
||||
} else if strings.HasPrefix(p, "wire=") {
|
||||
netConfig.Wire = p[len("wire="):]
|
||||
} else if p == "[random_exit]" {
|
||||
netConfig.Exit = true
|
||||
} else if p == "[random]" {
|
||||
netConfig.Exit = false
|
||||
} else if p == "[private]" {
|
||||
netConfig.Private = true
|
||||
} else if p == "[reserved]" {
|
||||
netConfig.Reserved = true
|
||||
} else if p == "[teaming]" {
|
||||
netConfig.RequireTeaming = true
|
||||
} else if p == "[try-teaming]" {
|
||||
netConfig.TryTeaming = true
|
||||
} else if strings.HasPrefix(p, "standby-port=") {
|
||||
netConfig.StandbyPortCount, _ = strconv.Atoi(p[len("standby-port="):])
|
||||
} else if strings.HasPrefix(p, "standby-addr=") {
|
||||
netConfig.StandbyAddrCount, _ = strconv.Atoi(p[len("standby-addr="):])
|
||||
} else if utils.IsInStringArray(p, []string{"virtio", "e1000", "vmxnet3"}) {
|
||||
netConfig.Driver = p
|
||||
} else if regutils.MatchSize(p) {
|
||||
bw, err := fileutils.GetSizeMb(p, 'M', 1000)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
netConfig.BwLimit = bw
|
||||
} else if p == "[vip]" {
|
||||
netConfig.Vip = true
|
||||
} else if utils.IsInStringArray(p, compute.ALL_NETWORK_TYPES) {
|
||||
netConfig.NetType = p
|
||||
} else {
|
||||
netConfig.Network = p
|
||||
}
|
||||
}
|
||||
return netConfig, nil
|
||||
}
|
||||
|
||||
func ParseIsolatedDevice(desc string, idx int) (*compute.IsolatedDeviceConfig, error) {
|
||||
if len(desc) == 0 {
|
||||
return nil, ErrorEmptyDesc
|
||||
}
|
||||
if idx < 0 {
|
||||
return nil, fmt.Errorf("Invalid index: %d", idx)
|
||||
}
|
||||
dev := new(compute.IsolatedDeviceConfig)
|
||||
parts := strings.Split(desc, ":")
|
||||
for _, p := range parts {
|
||||
if regutils.MatchUUIDExact(p) {
|
||||
dev.Id = p
|
||||
} else if utils.IsInStringArray(p, compute.VALID_PASSTHROUGH_TYPES) {
|
||||
dev.DevType = p
|
||||
} else if strings.HasPrefix(p, "vendor=") {
|
||||
dev.Vendor = p[len("vendor="):]
|
||||
} else {
|
||||
dev.Model = p
|
||||
}
|
||||
}
|
||||
return dev, nil
|
||||
}
|
||||
|
||||
func ParseBaremetalDiskConfig(desc string) (*compute.BaremetalDiskConfig, error) {
|
||||
bdc := new(compute.BaremetalDiskConfig)
|
||||
bdc.Type = compute.DISK_TYPE_HYBRID
|
||||
bdc.Conf = compute.DISK_CONF_NONE
|
||||
bdc.Count = 0
|
||||
desc = strings.ToLower(desc)
|
||||
if len(desc) == 0 {
|
||||
return bdc, nil
|
||||
}
|
||||
|
||||
parts := strings.Split(desc, ":")
|
||||
drvMap := make(map[string]string)
|
||||
for _, drv := range compute.DISK_DRIVERS.List() {
|
||||
drvMap[strings.ToLower(drv)] = drv
|
||||
}
|
||||
|
||||
for _, p := range parts {
|
||||
if len(p) == 0 {
|
||||
continue
|
||||
} else if utils.IsInStringArray(p, compute.DISK_TYPES) {
|
||||
bdc.Type = p
|
||||
} else if compute.DISK_CONFS.Has(p) {
|
||||
bdc.Conf = p
|
||||
} else if drv, ok := drvMap[p]; ok {
|
||||
bdc.Driver = drv
|
||||
} else if utils.IsMatchInteger(p) {
|
||||
bdc.Count, _ = strconv.ParseInt(p, 0, 0)
|
||||
} else if len(p) > 2 && p[0] == '[' && p[len(p)-1] == ']' {
|
||||
rg, err1 := ParseRange(p[1:(len(p) - 1)])
|
||||
if err1 != nil {
|
||||
return nil, err1
|
||||
}
|
||||
bdc.Range = rg
|
||||
} else if len(p) > 2 && p[0] == '(' && p[len(p)-1] == ')' {
|
||||
bdc.Splits = p[1 : len(p)-1]
|
||||
} else if utils.HasPrefix(p, "strip") {
|
||||
strip := parseStrip(p[len("strip"):], "k")
|
||||
bdc.Strip = &strip
|
||||
} else if utils.HasPrefix(p, "adapter") {
|
||||
ada, _ := strconv.ParseInt(p[len("adapter"):], 0, 64)
|
||||
pada := int(ada)
|
||||
bdc.Adapter = &pada
|
||||
} else if p == "ra" {
|
||||
hasRA := true
|
||||
bdc.RA = &hasRA
|
||||
} else if p == "nora" {
|
||||
noRA := false
|
||||
bdc.RA = &noRA
|
||||
} else if p == "wt" {
|
||||
wt := true
|
||||
bdc.WT = &wt
|
||||
} else if p == "wb" {
|
||||
wt := false
|
||||
bdc.WT = &wt
|
||||
} else if p == "direct" {
|
||||
direct := true
|
||||
bdc.Direct = &direct
|
||||
} else if p == "cached" {
|
||||
direct := false
|
||||
bdc.Direct = &direct
|
||||
} else if p == "cachedbadbbu" {
|
||||
cached := true
|
||||
bdc.Cachedbadbbu = &cached
|
||||
} else if p == "nocachedbadbbu" {
|
||||
cached := false
|
||||
bdc.Cachedbadbbu = &cached
|
||||
} else {
|
||||
return nil, fmt.Errorf("ParseDiskConfig unkown option %q", p)
|
||||
}
|
||||
}
|
||||
|
||||
return bdc, nil
|
||||
}
|
||||
|
||||
func ParseRange(rangeStr string) (ret []int64, err error) {
|
||||
rss := regexp.MustCompile(`[\s,]+`).Split(rangeStr, -1)
|
||||
intSet := sets.NewInt64()
|
||||
|
||||
for _, rs := range rss {
|
||||
r, err1 := _parseRange(rs)
|
||||
if err1 != nil {
|
||||
err = err1
|
||||
return
|
||||
}
|
||||
intSet.Insert(r...)
|
||||
}
|
||||
ret = intSet.List()
|
||||
return
|
||||
}
|
||||
|
||||
// range string should be: "1-3", "3"
|
||||
func _parseRange(str string) (ret []int64, err error) {
|
||||
if len(str) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// exclude "," symbol
|
||||
if len(str) == 1 && !utils.IsMatchInteger(str) {
|
||||
return
|
||||
}
|
||||
|
||||
// add int string
|
||||
if utils.IsMatchInteger(str) {
|
||||
i, _ := strconv.ParseInt(str, 10, 64)
|
||||
ret = append(ret, i)
|
||||
return
|
||||
}
|
||||
|
||||
// add rang like string, "2-10" etc.
|
||||
ret, err = parseRangeStr(str)
|
||||
return
|
||||
}
|
||||
|
||||
// return KB
|
||||
func parseStrip(stripStr string, defaultSize string) int64 {
|
||||
size, _ := utils.GetSize(stripStr, defaultSize, 1024)
|
||||
return size / 1024
|
||||
}
|
||||
|
||||
func parseRangeStr(str string) (ret []int64, err error) {
|
||||
im := utils.IsMatchInteger
|
||||
errGen := func(e string) error {
|
||||
return fmt.Errorf("Incorrect range str: %q", e)
|
||||
}
|
||||
rs := strings.Split(str, "-")
|
||||
if len(rs) != 2 {
|
||||
err = errGen(str)
|
||||
return
|
||||
}
|
||||
|
||||
bs, es := rs[0], rs[1]
|
||||
if !im(bs) {
|
||||
err = errGen(str)
|
||||
return
|
||||
}
|
||||
if !im(es) {
|
||||
err = errGen(str)
|
||||
return
|
||||
}
|
||||
|
||||
begin, _ := strconv.ParseInt(bs, 10, 64)
|
||||
end, _ := strconv.ParseInt(es, 10, 64)
|
||||
|
||||
if begin > end {
|
||||
begin, end = end, begin
|
||||
}
|
||||
|
||||
for i := begin; i <= end; i++ {
|
||||
ret = append(ret, i)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
package cmdline
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
func TestParseSchedtagConfig(t *testing.T) {
|
||||
type args struct {
|
||||
desc string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *compute.SchedtagConfig
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "empty input",
|
||||
args: args{""},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "normal",
|
||||
args: args{"ssd:require"},
|
||||
want: &compute.SchedtagConfig{Id: "ssd", Strategy: "require"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid strategy",
|
||||
args: args{"ssd:require2"},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := ParseSchedtagConfig(tt.args.desc)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ParseSchedtagConfig() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("ParseSchedtagConfig() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseRange(t *testing.T) {
|
||||
type args struct {
|
||||
rangeStr string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantRet []int64
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "range number and , test",
|
||||
args: args{"11-7,, 9-9, 10, 15, 1-2,4-5,,"},
|
||||
wantRet: []int64{1, 2, 4, 5, 7, 8, 9, 10, 11, 15},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "range,range",
|
||||
args: args{"1-2,4-5"},
|
||||
wantRet: []int64{1, 2, 4, 5},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "numbers",
|
||||
args: args{"1, 1"},
|
||||
wantRet: []int64{1},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "numbersErr",
|
||||
args: args{"1-, 1"},
|
||||
wantRet: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotRet, err := ParseRange(tt.args.rangeStr)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ParseRange() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(gotRet, tt.wantRet) {
|
||||
t.Errorf("ParseRange() = %v, want %v", gotRet, tt.wantRet)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchDiskConfigsByJSON(t *testing.T) {
|
||||
type args struct {
|
||||
obj jsonutils.JSONObject
|
||||
}
|
||||
|
||||
testDisks := []*compute.DiskConfig{
|
||||
{
|
||||
SizeMb: 1024,
|
||||
Medium: compute.DISK_TYPE_SSD,
|
||||
},
|
||||
{
|
||||
SizeMb: 2048,
|
||||
Medium: compute.DISK_TYPE_ROTATE,
|
||||
},
|
||||
}
|
||||
|
||||
testDisksObj := map[string][]*compute.DiskConfig{"disks": testDisks}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []*compute.DiskConfig
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
args: args{nil},
|
||||
want: nil,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "parse strings",
|
||||
args: args{obj: jsonutils.Marshal(
|
||||
map[string]string{
|
||||
"disk.0": "10g:/data1",
|
||||
"disk.1": "20g:ext4:ssd",
|
||||
},
|
||||
)},
|
||||
want: []*compute.DiskConfig{
|
||||
{
|
||||
Index: 0,
|
||||
SizeMb: 10 * 1024,
|
||||
Mountpoint: "/data1",
|
||||
Medium: compute.DISK_TYPE_HYBRID,
|
||||
},
|
||||
{
|
||||
Index: 1,
|
||||
SizeMb: 20 * 1024,
|
||||
Fs: "ext4",
|
||||
Medium: compute.DISK_TYPE_SSD,
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "parse struct",
|
||||
args: args{obj: jsonutils.Marshal(testDisksObj)},
|
||||
want: testDisks,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := FetchDiskConfigsByJSON(tt.args.obj)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("FetchDiskConfigsByJSON() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("FetchDiskConfigsByJSON() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,14 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
)
|
||||
|
||||
const (
|
||||
MIN_DB_CONN_MAX = 5
|
||||
)
|
||||
|
||||
func InitDB(options *DBOptions) {
|
||||
func InitDB(options *common_options.DBOptions) {
|
||||
if options.GlobalVirtualResourceNamespace {
|
||||
consts.EnableGlobalVirtualResourceNamespace()
|
||||
}
|
||||
|
||||
@@ -452,7 +452,9 @@ func ListItems(manager IModelManager, ctx context.Context, userCred mcclient.Tok
|
||||
if err == nil && colSpec != nil && colSpec.IsNumeric() {
|
||||
orderBy = []string{"id"}
|
||||
} else {
|
||||
orderBy = []string{"created_at"}
|
||||
if manager.TableSpec().ColumnSpec("created_at") != nil {
|
||||
orderBy = []string{"created_at"}
|
||||
}
|
||||
}
|
||||
}
|
||||
order := sqlchemy.SQL_ORDER_DESC
|
||||
|
||||
+158
-23
@@ -8,14 +8,24 @@ import (
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
const (
|
||||
SYSTEM_ADMIN_PREFIX = "__sys_"
|
||||
SYSTEM_ADMIN_PREFIX = "_"
|
||||
CLOUD_TAG_PREFIX = "ext:"
|
||||
USER_TAG_PREFIX = "user:"
|
||||
|
||||
TAG_DELETE_RANGE_USER = "user"
|
||||
TAG_DELETE_RANGE_CLOUD = "cloud"
|
||||
TAG_DELETE_RANGE_SYS = "sys"
|
||||
TAG_DELETE_RANGE_ALL = "all"
|
||||
)
|
||||
|
||||
type SMetadataManager struct {
|
||||
@@ -25,16 +35,24 @@ type SMetadataManager struct {
|
||||
type SMetadata struct {
|
||||
SModelBase
|
||||
|
||||
Id string `width:"128" charset:"ascii" primary:"true"` // = Column(VARCHAR(128, charset='ascii'), primary_key=True)
|
||||
Key string `width:"64" charset:"ascii" primary:"true"` // = Column(VARCHAR(64, charset='ascii'), primary_key=True)
|
||||
Value string `charset:"utf8"` // = Column(TEXT(charset='utf8'), nullable=True)
|
||||
UpdatedAt time.Time `nullable:"false" updated_at:"true"` // = Column(DateTime, default=get_utcnow, nullable=False, onupdate=get_utcnow)
|
||||
Id string `width:"128" charset:"ascii" primary:"true" list:"user" get:"user"` // = Column(VARCHAR(128, charset='ascii'), primary_key=True)
|
||||
Key string `width:"64" charset:"utf8" primary:"true" list:"user" get:"user"` // = Column(VARCHAR(64, charset='ascii'), primary_key=True)
|
||||
Value string `charset:"utf8" list:"user" get:"user"` // = Column(TEXT(charset='utf8'), nullable=True)
|
||||
UpdatedAt time.Time `nullable:"false" updated_at:"true"` // = Column(DateTime, default=get_utcnow, nullable=False, onupdate=get_utcnow)
|
||||
Deleted bool `nullable:"false" default:"false" index:"true"`
|
||||
}
|
||||
|
||||
var Metadata *SMetadataManager
|
||||
var ResourceMap map[string]*SVirtualResourceBaseManager
|
||||
|
||||
func init() {
|
||||
Metadata = &SMetadataManager{SModelBaseManager: NewModelBaseManager(SMetadata{}, "metadata_tbl", "metadata", "metadata")}
|
||||
Metadata = &SMetadataManager{SModelBaseManager: NewModelBaseManager(SMetadata{}, "metadata_tbl", "metadata", "metadatas")}
|
||||
ResourceMap = map[string]*SVirtualResourceBaseManager{
|
||||
"disk": {SStatusStandaloneResourceBaseManager: NewStatusStandaloneResourceBaseManager(SVirtualResourceBase{}, "disks_tbl", "disk", "disks")},
|
||||
"server": {SStatusStandaloneResourceBaseManager: NewStatusStandaloneResourceBaseManager(SVirtualResourceBase{}, "guests_tbl", "server", "servers")},
|
||||
"eip": {SStatusStandaloneResourceBaseManager: NewStatusStandaloneResourceBaseManager(SVirtualResourceBase{}, "elasticips_tbl", "eip", "eips")},
|
||||
"snapshot": {SStatusStandaloneResourceBaseManager: NewStatusStandaloneResourceBaseManager(SVirtualResourceBase{}, "snapshots_tbl", "snpashot", "snpashots")},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *SMetadata) GetId() string {
|
||||
@@ -53,6 +71,64 @@ func GetObjectIdstr(model IModel) string {
|
||||
return fmt.Sprintf("%s::%s", model.GetModelManager().Keyword(), model.GetId())
|
||||
}
|
||||
|
||||
func (manager *SMetadataManager) Query(fields ...string) *sqlchemy.SQuery {
|
||||
return manager.SModelBaseManager.Query(fields...).IsFalse("deleted")
|
||||
}
|
||||
|
||||
func (manager *SMetadataManager) RawQuery(fields ...string) *sqlchemy.SQuery {
|
||||
return manager.SModelBaseManager.Query(fields...)
|
||||
}
|
||||
|
||||
func (m *SMetadata) MarkDelete() error {
|
||||
m.Deleted = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *SMetadata) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return DeleteModel(ctx, userCred, m)
|
||||
}
|
||||
|
||||
func (manager *SMetadataManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (manager *SMetadataManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
||||
resources := jsonutils.GetQueryStringArray(query, "resources")
|
||||
if len(resources) == 0 {
|
||||
for resource := range ResourceMap {
|
||||
resources = append(resources, resource)
|
||||
}
|
||||
}
|
||||
conditions := []sqlchemy.ICondition{}
|
||||
admin := jsonutils.QueryBoolean(query, "admin", false)
|
||||
for _, resource := range resources {
|
||||
if manager, ok := ResourceMap[resource]; ok {
|
||||
resourceView := manager.Query().SubQuery()
|
||||
prefix := sqlchemy.NewStringField(fmt.Sprintf("%s::", manager.Keyword()))
|
||||
field := sqlchemy.CONCAT(manager.Keyword(), prefix, resourceView.Field("id"))
|
||||
sq := resourceView.Query(field)
|
||||
if !admin || !IsAdminAllowList(userCred, manager) {
|
||||
ownerId := manager.GetOwnerId(userCred)
|
||||
if len(ownerId) > 0 {
|
||||
sq = manager.FilterByOwner(sq, ownerId)
|
||||
}
|
||||
}
|
||||
conditions = append(conditions, sqlchemy.In(q.Field("id"), sq))
|
||||
} else {
|
||||
return nil, httperrors.NewInputParameterError("Not support resource %s tag filter", resource)
|
||||
}
|
||||
}
|
||||
if len(conditions) > 0 {
|
||||
q = q.Filter(sqlchemy.OR(conditions...))
|
||||
}
|
||||
for args, prefix := range map[string]string{"sys_meta": SYSTEM_ADMIN_PREFIX, "cloud_meta": CLOUD_TAG_PREFIX, "user_meta": USER_TAG_PREFIX} {
|
||||
if jsonutils.QueryBoolean(query, args, false) {
|
||||
q = q.Filter(sqlchemy.Startswith(q.Field("key"), prefix))
|
||||
}
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
/* @classmethod
|
||||
def get_object_idstr(cls, obj, keygen_func):
|
||||
idstr = None
|
||||
@@ -106,35 +182,42 @@ func (manager *SMetadataManager) RemoveAll(ctx context.Context, model IModel, us
|
||||
lockman.LockObject(ctx, model)
|
||||
defer lockman.ReleaseObject(ctx, model)
|
||||
|
||||
changes := []sMetadataChange{}
|
||||
records := make([]SMetadata, 0)
|
||||
q := manager.Query().Equals("id", idStr)
|
||||
err := FetchModelObjects(manager, q, &records)
|
||||
if err != nil {
|
||||
return fmt.Errorf("find metadata for %s fail: %s", idStr, err)
|
||||
}
|
||||
changes := make([]sMetadataChange, 0)
|
||||
for _, rec := range records {
|
||||
if len(rec.Value) > 0 {
|
||||
_, err := Update(&rec, func() error {
|
||||
rec.Value = ""
|
||||
return nil
|
||||
})
|
||||
if err == nil {
|
||||
changes = append(changes, sMetadataChange{Key: rec.Key, OValue: rec.Value})
|
||||
}
|
||||
if err = rec.Delete(ctx, userCred); err != nil {
|
||||
log.Errorf("remove metadata %v error: %v", rec, err)
|
||||
continue
|
||||
}
|
||||
changes = append(changes, sMetadataChange{Key: rec.Key, OValue: rec.Value})
|
||||
}
|
||||
if len(changes) > 0 {
|
||||
OpsLog.LogEvent(model, ACT_DEL_METADATA, jsonutils.Marshal(changes), userCred)
|
||||
OpsLog.LogEvent(model, ACT_SET_METADATA, jsonutils.Marshal(changes), userCred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SMetadataManager) SetValue(ctx context.Context, obj IModel, key string, value interface{}, userCred mcclient.TokenCredential) error {
|
||||
return manager.SetAll(ctx, obj, map[string]interface{}{key: value}, userCred)
|
||||
return manager.SetValuesWithLog(ctx, obj, map[string]interface{}{key: value}, userCred)
|
||||
}
|
||||
|
||||
func (manager *SMetadataManager) SetAll(ctx context.Context, obj IModel, store map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
func (manager *SMetadataManager) SetValuesWithLog(ctx context.Context, obj IModel, store map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
changes, err := manager.SetValues(ctx, obj, store, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(changes) > 0 {
|
||||
OpsLog.LogEvent(obj, ACT_SET_METADATA, jsonutils.Marshal(changes), userCred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SMetadataManager) SetValues(ctx context.Context, obj IModel, store map[string]interface{}, userCred mcclient.TokenCredential) ([]sMetadataChange, error) {
|
||||
idStr := GetObjectIdstr(obj)
|
||||
|
||||
lockman.LockObject(ctx, obj)
|
||||
@@ -142,13 +225,17 @@ func (manager *SMetadataManager) SetAll(ctx context.Context, obj IModel, store m
|
||||
|
||||
changes := make([]sMetadataChange, 0)
|
||||
for key, value := range store {
|
||||
if strings.HasPrefix(key, SYSTEM_ADMIN_PREFIX) && (userCred == nil || !IsAdminAllowGetSpec(userCred, obj, "metadata")) {
|
||||
return nil, httperrors.NewForbiddenError("Ordinary users can't set the tags that begin with an underscore")
|
||||
}
|
||||
|
||||
valStr := stringutils.Interface2String(value)
|
||||
valStrLower := strings.ToLower(valStr)
|
||||
if valStrLower == "none" || valStrLower == "null" {
|
||||
valStr = ""
|
||||
}
|
||||
record := SMetadata{}
|
||||
err := manager.Query().Equals("id", idStr).Equals("key", key).First(&record)
|
||||
err := manager.RawQuery().Equals("id", idStr).Equals("key", key).First(&record) //避免之前设置的tag被删除后再次设置时出现Duplicate entry error
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
changes = append(changes, sMetadataChange{Key: key, NValue: valStr})
|
||||
@@ -157,22 +244,70 @@ func (manager *SMetadataManager) SetAll(ctx context.Context, obj IModel, store m
|
||||
record.Value = valStr
|
||||
err = manager.TableSpec().Insert(&record)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
deleted := record.Deleted
|
||||
_, err := Update(&record, func() error {
|
||||
record.Deleted = false
|
||||
record.Value = valStr
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
if deleted {
|
||||
changes = append(changes, sMetadataChange{Key: key, NValue: valStr})
|
||||
} else {
|
||||
if record.Value != valStr {
|
||||
changes = append(changes, sMetadataChange{Key: key, OValue: record.Value, NValue: valStr})
|
||||
}
|
||||
}
|
||||
changes = append(changes, sMetadataChange{Key: key, OValue: record.Value, NValue: valStr})
|
||||
}
|
||||
}
|
||||
return changes, nil
|
||||
}
|
||||
|
||||
func (manager *SMetadataManager) SetAll(ctx context.Context, obj IModel, store map[string]interface{}, userCred mcclient.TokenCredential, delRange string) error {
|
||||
changes, err := manager.SetValues(ctx, obj, store, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
idStr := GetObjectIdstr(obj)
|
||||
|
||||
lockman.LockObject(ctx, obj)
|
||||
defer lockman.ReleaseObject(ctx, obj)
|
||||
|
||||
keys := []string{}
|
||||
for key := range store {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
|
||||
records := []SMetadata{}
|
||||
q := manager.Query().Equals("id", idStr)
|
||||
switch delRange {
|
||||
case TAG_DELETE_RANGE_USER:
|
||||
q = q.Like("key", USER_TAG_PREFIX+"%")
|
||||
case TAG_DELETE_RANGE_CLOUD:
|
||||
q = q.Like("key", CLOUD_TAG_PREFIX+"%")
|
||||
case TAG_DELETE_RANGE_SYS:
|
||||
q = q.Like("key", SYSTEM_ADMIN_PREFIX+"%")
|
||||
}
|
||||
q = q.Filter(sqlchemy.NOT(sqlchemy.In(q.Field("key"), keys)))
|
||||
if err := FetchModelObjects(manager, q, &records); err != nil {
|
||||
log.Errorf("failed to fetch metadata error: %v", err)
|
||||
}
|
||||
for _, rec := range records {
|
||||
if err := rec.Delete(ctx, userCred); err != nil {
|
||||
log.Errorf("failed to delete metadata error: %v", err)
|
||||
continue
|
||||
}
|
||||
changes = append(changes, sMetadataChange{Key: rec.Key, OValue: rec.Value})
|
||||
}
|
||||
if len(changes) > 0 {
|
||||
OpsLog.LogEvent(obj, ACT_SET_METADATA, jsonutils.Marshal(changes), userCred)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package db
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
@@ -103,6 +105,11 @@ func (manager *SStandaloneResourceBaseManager) FetchByExternalId(idStr string) (
|
||||
}
|
||||
}
|
||||
|
||||
type STagValue struct {
|
||||
value string
|
||||
exist bool
|
||||
}
|
||||
|
||||
func (manager *SStandaloneResourceBaseManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
@@ -114,6 +121,62 @@ func (manager *SStandaloneResourceBaseManager) ListItemFilter(ctx context.Contex
|
||||
q = q.Filter(sqlchemy.IsFalse(q.Field("is_emulated")))
|
||||
}
|
||||
|
||||
tags := map[string]STagValue{}
|
||||
if query.Contains("tags") {
|
||||
idx := 0
|
||||
for {
|
||||
key, _ := query.GetString("tags", fmt.Sprintf("%d", idx), "key")
|
||||
if len(key) == 0 {
|
||||
break
|
||||
}
|
||||
value := STagValue{exist: false}
|
||||
if query.Contains("tags", fmt.Sprintf("%d", idx), "value") {
|
||||
value.value, _ = query.GetString("tags", fmt.Sprintf("%d", idx), "value")
|
||||
value.exist = true
|
||||
}
|
||||
tags[key] = value
|
||||
idx++
|
||||
}
|
||||
}
|
||||
|
||||
if len(tags) > 0 {
|
||||
metadataView := Metadata.Query("id")
|
||||
idx := 0
|
||||
for k, v := range tags {
|
||||
if idx == 0 {
|
||||
metadataView = metadataView.Equals("key", k)
|
||||
if v.exist {
|
||||
metadataView = metadataView.Equals("value", v.value)
|
||||
}
|
||||
} else {
|
||||
subMetataView := Metadata.Query().Equals("key", k)
|
||||
if v.exist {
|
||||
subMetataView = subMetataView.Equals("value", v.value)
|
||||
}
|
||||
sq := subMetataView.SubQuery()
|
||||
metadataView.Join(sq, sqlchemy.Equals(metadataView.Field("id"), sq.Field("id")))
|
||||
}
|
||||
idx++
|
||||
}
|
||||
metadataView = metadataView.Filter(sqlchemy.Like(metadataView.Field("id"), manager.Keyword()+"::%")).Distinct()
|
||||
resourceIds := []string{}
|
||||
rows, err := metadataView.Rows()
|
||||
if err != nil {
|
||||
log.Errorf("query metadata ids error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var metadataID string
|
||||
err = rows.Scan(&metadataID)
|
||||
if err != nil {
|
||||
log.Errorf("get metadata id scan error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
resourceIds = append(resourceIds, strings.TrimLeft(metadataID, manager.Keyword()+"::"))
|
||||
}
|
||||
q = q.Filter(sqlchemy.In(q.Field("id"), resourceIds))
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
@@ -163,7 +226,15 @@ func (model *SStandaloneResourceBase) SetAllMetadata(ctx context.Context, dictst
|
||||
return httperrors.NewNotSufficientPrivilegeError("not allow to set system key %s", k)
|
||||
}
|
||||
}
|
||||
return Metadata.SetAll(ctx, model, dictstore, userCred)
|
||||
return Metadata.SetValuesWithLog(ctx, model, dictstore, userCred)
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) SetUserMetadataValues(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
return Metadata.SetValuesWithLog(ctx, model, dictstore, userCred)
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) SetUserMetadataAll(ctx context.Context, dictstore map[string]interface{}, userCred mcclient.TokenCredential) error {
|
||||
return Metadata.SetAll(ctx, model, dictstore, userCred, "user")
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) RemoveMetadata(ctx context.Context, key string, userCred mcclient.TokenCredential) error {
|
||||
@@ -212,6 +283,48 @@ func (model *SStandaloneResourceBase) PerformMetadata(ctx context.Context, userC
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) AllowPerformUserMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return IsAdminAllowPerform(userCred, model, "user-metadata")
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) PerformUserMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
dict, ok := data.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
return nil, httperrors.NewInputParameterError("input data not key value dict")
|
||||
}
|
||||
dictMap, err := dict.GetMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dictStore := make(map[string]interface{})
|
||||
for k, v := range dictMap {
|
||||
dictStore["user:"+k], _ = v.GetString()
|
||||
}
|
||||
err = model.SetUserMetadataValues(ctx, dictStore, userCred)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) AllowPerformSetUserMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
return IsAdminAllowPerform(userCred, model, "set-user-metadata")
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) PerformSetUserMetadata(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
dict, ok := data.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
return nil, httperrors.NewInputParameterError("input data not key value dict")
|
||||
}
|
||||
dictMap, err := dict.GetMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dictStore := make(map[string]interface{})
|
||||
for k, v := range dictMap {
|
||||
dictStore["user:"+k], _ = v.GetString()
|
||||
}
|
||||
err = model.SetUserMetadataAll(ctx, dictStore, userCred)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (model *SStandaloneResourceBase) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
extra := model.SResourceBase.GetCustomizeColumns(ctx, userCred, query)
|
||||
withMeta, _ := query.GetString("with_meta")
|
||||
|
||||
@@ -133,6 +133,7 @@ func (model *SVirtualResourceBase) CustomizeCreate(ctx context.Context, userCred
|
||||
} else {
|
||||
model.IsSystem = false
|
||||
}
|
||||
model.ProjectSrc = string(PROJECT_SOURCE_LOCAL)
|
||||
return model.SStandaloneResourceBase.CustomizeCreate(ctx, userCred, ownerProjId, query, data)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package options // import "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
@@ -1,4 +1,4 @@
|
||||
package cloudcommon
|
||||
package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -1 +0,0 @@
|
||||
package storagetypes // import "yunion.io/x/onecloud/pkg/cloudcommon/storagetypes"
|
||||
@@ -1,18 +0,0 @@
|
||||
package storagetypes
|
||||
|
||||
// TODO: move models/storages.go storage types to this file
|
||||
var (
|
||||
STORAGE_LOCAL = "local"
|
||||
STORAGE_BAREMETAL = "baremetal"
|
||||
STORAGE_SHEEPDOG = "sheepdog"
|
||||
STORAGE_RBD = "rbd"
|
||||
STORAGE_DOCKER = "docker"
|
||||
STORAGE_NAS = "nas"
|
||||
STORAGE_VSAN = "vsan"
|
||||
STORAGE_NFS = "nfs"
|
||||
|
||||
DISK_TYPE_ROTATE = "rotate"
|
||||
DISK_TYPE_SSD = "ssd"
|
||||
|
||||
Local = []string{STORAGE_LOCAL, STORAGE_BAREMETAL, STORAGE_NAS}
|
||||
)
|
||||
@@ -1,14 +1,14 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/etcd"
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
)
|
||||
|
||||
type SCloudirOptions struct {
|
||||
etcd.SEtcdOptions
|
||||
|
||||
cloudcommon.CommonOptions
|
||||
common_options.CommonOptions
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -6,16 +6,18 @@ import (
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon"
|
||||
app_common "yunion.io/x/onecloud/pkg/cloudcommon/app"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/etcd"
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
"yunion.io/x/onecloud/pkg/cloudir/options"
|
||||
)
|
||||
|
||||
func StartService() {
|
||||
opts := &options.Options
|
||||
commonOpts := &opts.CommonOptions
|
||||
cloudcommon.ParseOptions(opts, os.Args, "cloudir.conf", "cloudir")
|
||||
common_options.ParseOptions(opts, os.Args, "cloudir.conf", "cloudir")
|
||||
|
||||
cloudcommon.InitAuth(commonOpts, func() {
|
||||
app_common.InitAuth(commonOpts, func() {
|
||||
log.Infof("Auth complete!!")
|
||||
})
|
||||
|
||||
@@ -25,11 +27,11 @@ func StartService() {
|
||||
return
|
||||
}
|
||||
|
||||
app := cloudcommon.InitApp(commonOpts, false)
|
||||
|
||||
app := app_common.InitApp(commonOpts, false)
|
||||
cloudcommon.AppDBInit(app)
|
||||
initHandlers(app)
|
||||
|
||||
cloudcommon.ServeForeverWithCleanup(app, commonOpts, func() {
|
||||
app_common.ServeForeverWithCleanup(app, commonOpts, func() {
|
||||
etcd.CloseDefaultEtcdClient()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ func GetPublicProviders() []string {
|
||||
func GetPrivateProviders() []string {
|
||||
providers := make([]string, 0)
|
||||
for p, d := range providerTable {
|
||||
if !d.IsPublicCloud() {
|
||||
if !d.IsPublicCloud() && !d.IsOnPremise() {
|
||||
providers = append(providers, p)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/etcd"
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
)
|
||||
|
||||
type CloudSyncOptions struct {
|
||||
@@ -13,7 +13,7 @@ type CloudSyncOptions struct {
|
||||
|
||||
etcd.SEtcdOptions
|
||||
|
||||
cloudcommon.CommonOptions
|
||||
common_options.CommonOptions
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -6,8 +6,10 @@ import (
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon"
|
||||
app_common "yunion.io/x/onecloud/pkg/cloudcommon/app"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/etcd"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/etcd/models"
|
||||
common_options "yunion.io/x/onecloud/pkg/cloudcommon/options"
|
||||
"yunion.io/x/onecloud/pkg/cloutpost/options"
|
||||
)
|
||||
|
||||
@@ -18,9 +20,9 @@ const (
|
||||
func StartService() {
|
||||
opts := &options.Options
|
||||
commonOpts := &opts.CommonOptions
|
||||
cloudcommon.ParseOptions(opts, os.Args, "cloutpost.conf", SERVICE_TYPE)
|
||||
common_options.ParseOptions(opts, os.Args, "cloutpost.conf", SERVICE_TYPE)
|
||||
|
||||
cloudcommon.InitAuth(commonOpts, func() {
|
||||
app_common.InitAuth(commonOpts, func() {
|
||||
log.Infof("Auth complete!!")
|
||||
})
|
||||
|
||||
@@ -30,8 +32,8 @@ func StartService() {
|
||||
}
|
||||
defer etcd.CloseDefaultEtcdClient()
|
||||
|
||||
app := cloudcommon.InitApp(commonOpts, false)
|
||||
|
||||
app := app_common.InitApp(commonOpts, false)
|
||||
cloudcommon.AppDBInit(app)
|
||||
initHandlers(app)
|
||||
|
||||
err = models.ServiceRegistryManager.Register(
|
||||
@@ -49,5 +51,5 @@ func StartService() {
|
||||
log.Fatalf("fail to register service %s", err)
|
||||
}
|
||||
|
||||
cloudcommon.ServeForever(app, commonOpts)
|
||||
app_common.ServeForever(app, commonOpts)
|
||||
}
|
||||
|
||||
@@ -4,171 +4,27 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/sets"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/cmdline"
|
||||
)
|
||||
|
||||
// return bytes
|
||||
func parseStrip(stripStr string, defaultSize string) int64 {
|
||||
size, _ := utils.GetSize(stripStr, defaultSize, 1024)
|
||||
return size / 1024
|
||||
}
|
||||
|
||||
func parseRangeStr(str string) (ret []int64, err error) {
|
||||
im := utils.IsMatchInteger
|
||||
errGen := func(e string) error {
|
||||
return fmt.Errorf("Incorrect range str: %q", e)
|
||||
func ParseDiskConfig(desc string) (api.BaremetalDiskConfig, error) {
|
||||
conf, err := cmdline.ParseBaremetalDiskConfig(desc)
|
||||
if err != nil {
|
||||
return api.BaremetalDiskConfig{}, err
|
||||
}
|
||||
rs := strings.Split(str, "-")
|
||||
if len(rs) != 2 {
|
||||
err = errGen(str)
|
||||
return
|
||||
}
|
||||
|
||||
bs, es := rs[0], rs[1]
|
||||
if !im(bs) {
|
||||
err = errGen(str)
|
||||
return
|
||||
}
|
||||
if !im(es) {
|
||||
err = errGen(str)
|
||||
return
|
||||
}
|
||||
|
||||
begin, _ := strconv.ParseInt(bs, 10, 64)
|
||||
end, _ := strconv.ParseInt(es, 10, 64)
|
||||
|
||||
if begin > end {
|
||||
begin, end = end, begin
|
||||
}
|
||||
|
||||
for i := begin; i <= end; i++ {
|
||||
ret = append(ret, i)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// range string should be: "1-3", "3"
|
||||
func _parseRange(str string) (ret []int64, err error) {
|
||||
if len(str) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// exclude "," symbol
|
||||
if len(str) == 1 && !utils.IsMatchInteger(str) {
|
||||
return
|
||||
}
|
||||
|
||||
// add int string
|
||||
if utils.IsMatchInteger(str) {
|
||||
i, _ := strconv.ParseInt(str, 10, 64)
|
||||
ret = append(ret, i)
|
||||
return
|
||||
}
|
||||
|
||||
// add rang like string, "2-10" etc.
|
||||
ret, err = parseRangeStr(str)
|
||||
return
|
||||
}
|
||||
|
||||
func ParseRange(rangeStr string) (ret []int64, err error) {
|
||||
rss := regexp.MustCompile(`[\s,]+`).Split(rangeStr, -1)
|
||||
intSet := sets.NewInt64()
|
||||
|
||||
for _, rs := range rss {
|
||||
r, err1 := _parseRange(rs)
|
||||
if err1 != nil {
|
||||
err = err1
|
||||
return
|
||||
}
|
||||
intSet.Insert(r...)
|
||||
}
|
||||
ret = intSet.List()
|
||||
return
|
||||
}
|
||||
|
||||
func ParseDiskConfig(desc string) (bdc BaremetalDiskConfig, err error) {
|
||||
bdc.Type = DISK_TYPE_HYBRID
|
||||
bdc.Conf = DISK_CONF_NONE
|
||||
bdc.Count = 0
|
||||
|
||||
desc = strings.ToLower(desc)
|
||||
if desc == "" {
|
||||
return
|
||||
}
|
||||
|
||||
parts := strings.Split(desc, ":")
|
||||
drvMap := make(map[string]string)
|
||||
for _, drv := range DISK_DRIVERS.List() {
|
||||
drvMap[strings.ToLower(drv)] = drv
|
||||
}
|
||||
for _, p := range parts {
|
||||
if len(p) == 0 {
|
||||
continue
|
||||
} else if DISK_TYPES.Has(p) {
|
||||
bdc.Type = p
|
||||
} else if DISK_CONFS.Has(p) {
|
||||
bdc.Conf = p
|
||||
} else if drv, ok := drvMap[p]; ok {
|
||||
bdc.Driver = drv
|
||||
} else if utils.IsMatchInteger(p) {
|
||||
bdc.Count, _ = strconv.ParseInt(p, 0, 0)
|
||||
} else if len(p) > 2 && p[0] == '[' && p[len(p)-1] == ']' {
|
||||
rg, err1 := ParseRange(p[1:(len(p) - 1)])
|
||||
if err1 != nil {
|
||||
err = err1
|
||||
return
|
||||
}
|
||||
bdc.Range = rg
|
||||
} else if len(p) > 2 && p[0] == '(' && p[len(p)-1] == ')' {
|
||||
bdc.Splits = p[1 : len(p)-1]
|
||||
} else if utils.HasPrefix(p, "strip") {
|
||||
strip := parseStrip(p[len("strip"):], "k")
|
||||
bdc.Strip = &strip
|
||||
} else if utils.HasPrefix(p, "adapter") {
|
||||
ada, _ := strconv.ParseInt(p[len("adapter"):], 0, 64)
|
||||
pada := int(ada)
|
||||
bdc.Adapter = &pada
|
||||
} else if p == "ra" {
|
||||
hasRA := true
|
||||
bdc.RA = &hasRA
|
||||
} else if p == "nora" {
|
||||
noRA := false
|
||||
bdc.RA = &noRA
|
||||
} else if p == "wt" {
|
||||
wt := true
|
||||
bdc.WT = &wt
|
||||
} else if p == "wb" {
|
||||
wt := false
|
||||
bdc.WT = &wt
|
||||
} else if p == "direct" {
|
||||
direct := true
|
||||
bdc.Direct = &direct
|
||||
} else if p == "cached" {
|
||||
direct := false
|
||||
bdc.Direct = &direct
|
||||
} else if p == "cachedbadbbu" {
|
||||
cached := true
|
||||
bdc.Cachedbadbbu = &cached
|
||||
} else if p == "nocachedbadbbu" {
|
||||
cached := false
|
||||
bdc.Cachedbadbbu = &cached
|
||||
} else {
|
||||
err = fmt.Errorf("ParseDiskConfig unkown option %q", p)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
return *conf, nil
|
||||
}
|
||||
|
||||
func isDiskConfigStorageMatch(
|
||||
config *BaremetalDiskConfig,
|
||||
config *api.BaremetalDiskConfig,
|
||||
confDriver *string,
|
||||
confAdapter *int,
|
||||
storage *BaremetalStorage,
|
||||
@@ -198,7 +54,7 @@ func isDiskConfigStorageMatch(
|
||||
return false
|
||||
}
|
||||
|
||||
func RetrieveStorages(diskConfig *BaremetalDiskConfig, storages []*BaremetalStorage) (selected, rest []*BaremetalStorage) {
|
||||
func RetrieveStorages(diskConfig *api.BaremetalDiskConfig, storages []*BaremetalStorage) (selected, rest []*BaremetalStorage) {
|
||||
var confDriver *string = nil
|
||||
var confAdapter *int = nil
|
||||
|
||||
@@ -259,9 +115,9 @@ func RequireEvenDisks(diskConfig string) bool {
|
||||
}
|
||||
|
||||
type Layout struct {
|
||||
Disks []*BaremetalStorage `json:"disks"`
|
||||
Conf *BaremetalDiskConfig `json:"conf"`
|
||||
Size int64 `json:"size"`
|
||||
Disks []*BaremetalStorage `json:"disks"`
|
||||
Conf *api.BaremetalDiskConfig `json:"conf"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
func (l Layout) String() string {
|
||||
@@ -280,7 +136,7 @@ func RetrieveStorageDrivers(storages []*BaremetalStorage) sets.String {
|
||||
}
|
||||
|
||||
func MeetConfig(
|
||||
conf *BaremetalDiskConfig,
|
||||
conf *api.BaremetalDiskConfig,
|
||||
storages []*BaremetalStorage,
|
||||
) error {
|
||||
storageDrvs := RetrieveStorageDrivers(storages)
|
||||
@@ -417,9 +273,9 @@ func ExpandNoneConf(layouts []Layout) (ret []Layout) {
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetLayoutRaidConfig(layouts []Layout) []*BaremetalDiskConfig {
|
||||
func GetLayoutRaidConfig(layouts []Layout) []*api.BaremetalDiskConfig {
|
||||
var disk []*BaremetalStorage
|
||||
ret := make([]*BaremetalDiskConfig, 0)
|
||||
ret := make([]*api.BaremetalDiskConfig, 0)
|
||||
for _, layout := range layouts {
|
||||
if layout.Conf.Conf == DISK_CONF_NONE &&
|
||||
sets.NewString(DISK_DRIVER_LINUX, DISK_DRIVER_PCIE).Has(layout.Disks[0].Driver) {
|
||||
@@ -444,10 +300,10 @@ func GetLayoutRaidConfig(layouts []Layout) []*BaremetalDiskConfig {
|
||||
return ret
|
||||
}
|
||||
|
||||
func CalculateLayout(confs []*BaremetalDiskConfig, storages []*BaremetalStorage) (layouts []Layout, err error) {
|
||||
func CalculateLayout(confs []*api.BaremetalDiskConfig, storages []*BaremetalStorage) (layouts []Layout, err error) {
|
||||
var confIdx = 0
|
||||
for len(storages) > 0 {
|
||||
var conf *BaremetalDiskConfig
|
||||
var conf *api.BaremetalDiskConfig
|
||||
if confIdx < len(confs) {
|
||||
conf = confs[confIdx]
|
||||
confIdx += 1
|
||||
@@ -544,8 +400,8 @@ func CheckDisksAllocable(layouts []Layout, disks []*Disk) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func NewBaremetalDiskConfigs(dss ...string) ([]*BaremetalDiskConfig, error) {
|
||||
ret := make([]*BaremetalDiskConfig, 0)
|
||||
func NewBaremetalDiskConfigs(dss ...string) ([]*api.BaremetalDiskConfig, error) {
|
||||
ret := make([]*api.BaremetalDiskConfig, 0)
|
||||
for _, ds := range dss {
|
||||
r, err := ParseDiskConfig(ds)
|
||||
if err != nil {
|
||||
@@ -671,7 +527,7 @@ func GetDiskConfigurations(layouts []Layout) []DiskConfiguration {
|
||||
type DriverAdapterDiskConfig struct {
|
||||
Driver string
|
||||
Adapter int
|
||||
Configs []*BaremetalDiskConfig
|
||||
Configs []*api.BaremetalDiskConfig
|
||||
}
|
||||
|
||||
func GroupLayoutResultsByDriverAdapter(layouts []Layout) []*DriverAdapterDiskConfig {
|
||||
@@ -687,7 +543,7 @@ func GroupLayoutResultsByDriverAdapter(layouts []Layout) []*DriverAdapterDiskCon
|
||||
item := &DriverAdapterDiskConfig{
|
||||
Driver: driver,
|
||||
Adapter: adapter,
|
||||
Configs: []*BaremetalDiskConfig{layout.Conf},
|
||||
Configs: []*api.BaremetalDiskConfig{layout.Conf},
|
||||
}
|
||||
ret = append(ret, item)
|
||||
tbl[key] = item
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
func TestParseDiskConfig(t *testing.T) {
|
||||
@@ -22,13 +24,13 @@ func TestParseDiskConfig(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantBdc BaremetalDiskConfig
|
||||
wantBdc api.BaremetalDiskConfig
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "rotate:[1-2,4-5]:MegaRaid",
|
||||
args: args{"rotate:[1-2,4-5]:MegaRaid"},
|
||||
wantBdc: BaremetalDiskConfig{
|
||||
wantBdc: api.BaremetalDiskConfig{
|
||||
Type: DISK_TYPE_ROTATE,
|
||||
Conf: DISK_CONF_NONE,
|
||||
Driver: DISK_DRIVER_MEGARAID,
|
||||
@@ -40,7 +42,7 @@ func TestParseDiskConfig(t *testing.T) {
|
||||
{
|
||||
name: "rotate:[1-2,4,6]:raid10:marvelraid",
|
||||
args: args{"rotate:[1-2,4,6]:raid10:marvelraid"},
|
||||
wantBdc: BaremetalDiskConfig{
|
||||
wantBdc: api.BaremetalDiskConfig{
|
||||
Type: DISK_TYPE_ROTATE,
|
||||
Conf: DISK_CONF_RAID10,
|
||||
Driver: DISK_DRIVER_MARVELRAID,
|
||||
@@ -52,7 +54,7 @@ func TestParseDiskConfig(t *testing.T) {
|
||||
{
|
||||
name: "rotate:[4,6]:raid10",
|
||||
args: args{"rotate:[4,6]:raid10"},
|
||||
wantBdc: BaremetalDiskConfig{
|
||||
wantBdc: api.BaremetalDiskConfig{
|
||||
Type: DISK_TYPE_ROTATE,
|
||||
Conf: DISK_CONF_RAID10,
|
||||
Count: 0,
|
||||
@@ -63,7 +65,7 @@ func TestParseDiskConfig(t *testing.T) {
|
||||
{
|
||||
name: "rotate:[4]:raid10:(40%, )",
|
||||
args: args{"rotate:[4]:raid10:(40%, )"},
|
||||
wantBdc: BaremetalDiskConfig{
|
||||
wantBdc: api.BaremetalDiskConfig{
|
||||
Type: DISK_TYPE_ROTATE,
|
||||
Conf: DISK_CONF_RAID10,
|
||||
Count: 0,
|
||||
@@ -75,7 +77,7 @@ func TestParseDiskConfig(t *testing.T) {
|
||||
{
|
||||
name: "[12-13]:raid1:(100g,32g,):adapter0:strip64k",
|
||||
args: args{"[12-13]:raid1:(100g,32g,):adapter0:strip64k"},
|
||||
wantBdc: BaremetalDiskConfig{
|
||||
wantBdc: api.BaremetalDiskConfig{
|
||||
Type: DISK_TYPE_HYBRID,
|
||||
Conf: DISK_CONF_RAID1,
|
||||
Count: 0,
|
||||
@@ -89,7 +91,7 @@ func TestParseDiskConfig(t *testing.T) {
|
||||
{
|
||||
name: "6:raid5:adapter2",
|
||||
args: args{"6:raid5:adapter2"},
|
||||
wantBdc: BaremetalDiskConfig{
|
||||
wantBdc: api.BaremetalDiskConfig{
|
||||
Type: DISK_TYPE_HYBRID,
|
||||
Conf: DISK_CONF_RAID5,
|
||||
Count: 6,
|
||||
@@ -112,55 +114,6 @@ func TestParseDiskConfig(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseRange(t *testing.T) {
|
||||
type args struct {
|
||||
rangeStr string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantRet []int64
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "range number and , test",
|
||||
args: args{"11-7,, 9-9, 10, 15, 1-2,4-5,,"},
|
||||
wantRet: []int64{1, 2, 4, 5, 7, 8, 9, 10, 11, 15},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "range,range",
|
||||
args: args{"1-2,4-5"},
|
||||
wantRet: []int64{1, 2, 4, 5},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "numbers",
|
||||
args: args{"1, 1"},
|
||||
wantRet: []int64{1},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "numbersErr",
|
||||
args: args{"1-, 1"},
|
||||
wantRet: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
gotRet, err := ParseRange(tt.args.rangeStr)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ParseRange() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(gotRet, tt.wantRet) {
|
||||
t.Errorf("ParseRange() = %v, want %v", gotRet, tt.wantRet)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
testStorages = []*BaremetalStorage{
|
||||
// 0-11 disk on adapter2
|
||||
@@ -516,7 +469,7 @@ func TestCheckDisksAllocable(t *testing.T) {
|
||||
}
|
||||
|
||||
layout, err := CalculateLayout(confs, testStorages)
|
||||
defaultLayout, err := CalculateLayout([]*BaremetalDiskConfig{&BaremetalDefaultDiskConfig}, testStorages[12:])
|
||||
defaultLayout, err := CalculateLayout([]*api.BaremetalDiskConfig{&BaremetalDefaultDiskConfig}, testStorages[12:])
|
||||
if err != nil {
|
||||
t.Fatalf("CalculateLayout err: %v", err)
|
||||
}
|
||||
|
||||
@@ -3,66 +3,45 @@ package baremetal
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"yunion.io/x/pkg/util/sets"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
const (
|
||||
DISK_CONF_RAID0 = "raid0"
|
||||
DISK_CONF_RAID1 = "raid1"
|
||||
DISK_CONF_RAID5 = "raid5"
|
||||
DISK_CONF_RAID10 = "raid10"
|
||||
DISK_CONF_NONE = "none"
|
||||
DISK_CONF_RAID0 = api.DISK_CONF_RAID0
|
||||
DISK_CONF_RAID1 = api.DISK_CONF_RAID1
|
||||
DISK_CONF_RAID5 = api.DISK_CONF_RAID5
|
||||
DISK_CONF_RAID10 = api.DISK_CONF_RAID10
|
||||
DISK_CONF_NONE = api.DISK_CONF_NONE
|
||||
|
||||
DEFAULT_DISK_CONF = DISK_CONF_NONE
|
||||
DEFAULT_DISK_CONF = api.DEFAULT_DISK_CONF
|
||||
|
||||
DISK_TYPE_ROTATE = "rotate"
|
||||
DISK_TYPE_SSD = "ssd"
|
||||
DISK_TYPE_HYBRID = "hybrid"
|
||||
DISK_TYPE_ROTATE = api.DISK_TYPE_ROTATE
|
||||
DISK_TYPE_SSD = api.DISK_TYPE_SSD
|
||||
DISK_TYPE_HYBRID = api.DISK_TYPE_HYBRID
|
||||
|
||||
DEFAULT_DISK_TYPE = DISK_TYPE_ROTATE
|
||||
DEFAULT_DISK_TYPE = api.DEFAULT_DISK_TYPE
|
||||
|
||||
DISK_DRIVER_MEGARAID = "MegaRaid"
|
||||
DISK_DRIVER_LINUX = "Linux"
|
||||
DISK_DRIVER_HPSARAID = "HPSARaid"
|
||||
DISK_DRIVER_MPT2SAS = "Mpt2SAS"
|
||||
DISK_DRIVER_MARVELRAID = "MarvelRaid"
|
||||
DISK_DRIVER_PCIE = "PCIE"
|
||||
DISK_DRIVER_MEGARAID = api.DISK_DRIVER_MEGARAID
|
||||
DISK_DRIVER_LINUX = api.DISK_DRIVER_LINUX
|
||||
DISK_DRIVER_HPSARAID = api.DISK_DRIVER_HPSARAID
|
||||
DISK_DRIVER_MPT2SAS = api.DISK_DRIVER_MPT2SAS
|
||||
DISK_DRIVER_MARVELRAID = api.DISK_DRIVER_MARVELRAID
|
||||
DISK_DRIVER_PCIE = api.DISK_DRIVER_PCIE
|
||||
|
||||
HDD_DISK_SPEC_TYPE = "HDD"
|
||||
SSD_DISK_SPEC_TYPE = "SSD"
|
||||
HDD_DISK_SPEC_TYPE = api.HDD_DISK_SPEC_TYPE
|
||||
SSD_DISK_SPEC_TYPE = api.SSD_DISK_SPEC_TYPE
|
||||
)
|
||||
|
||||
var (
|
||||
BaremetalDefaultDiskConfig = BaremetalDiskConfig{
|
||||
Type: DISK_TYPE_HYBRID,
|
||||
Conf: DISK_CONF_NONE,
|
||||
Count: 0,
|
||||
}
|
||||
BaremetalDefaultDiskConfig = api.BaremetalDefaultDiskConfig
|
||||
|
||||
DISK_CONFS = sets.NewString(
|
||||
DISK_CONF_RAID0,
|
||||
DISK_CONF_RAID1,
|
||||
DISK_CONF_RAID5,
|
||||
DISK_CONF_RAID10,
|
||||
DISK_CONF_NONE,
|
||||
)
|
||||
DISK_CONFS = api.DISK_CONFS
|
||||
|
||||
DISK_TYPES = sets.NewString(
|
||||
DISK_TYPE_ROTATE,
|
||||
DISK_TYPE_SSD,
|
||||
DISK_TYPE_HYBRID,
|
||||
)
|
||||
DISK_TYPES = api.DISK_TYPES
|
||||
|
||||
DISK_DRIVERS_RAID = sets.NewString(
|
||||
DISK_DRIVER_MEGARAID,
|
||||
DISK_DRIVER_HPSARAID,
|
||||
DISK_DRIVER_MPT2SAS,
|
||||
DISK_DRIVER_MARVELRAID,
|
||||
)
|
||||
DISK_DRIVERS_RAID = api.DISK_DRIVERS_RAID
|
||||
|
||||
DISK_DRIVERS = sets.NewString(
|
||||
DISK_DRIVER_LINUX,
|
||||
DISK_DRIVER_PCIE).Union(DISK_DRIVERS_RAID)
|
||||
DISK_DRIVERS = api.DISK_DRIVERS
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -99,24 +78,6 @@ func (s BaremetalStorage) GetBlock() int64 {
|
||||
return s.Block
|
||||
}
|
||||
|
||||
type BaremetalDiskConfig struct {
|
||||
// disk type
|
||||
Type string `json:"type"`
|
||||
// raid config
|
||||
Conf string `json:"conf"`
|
||||
Count int64 `json:"count"`
|
||||
Range []int64 `json:"range"`
|
||||
Splits string `json:"splits"`
|
||||
Size []int64 `json:"size"`
|
||||
Adapter *int `json:"adapter,omitempty"`
|
||||
Driver string `json:"driver"`
|
||||
Cachedbadbbu *bool `json:"cachedbadbbu,omitempty"`
|
||||
Strip *int64 `json:"strip,omitempty"`
|
||||
RA *bool `json:"ra,omitempty"`
|
||||
WT *bool `json:"wt,omitempty"`
|
||||
Direct *bool `json:"direct,omitempty"`
|
||||
}
|
||||
|
||||
type Disk struct {
|
||||
Backend string `json:"backend"`
|
||||
ImageID string `json:"image_id"`
|
||||
|
||||
@@ -25,7 +25,7 @@ func capaHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||
httperrors.GeneralServerError(w, err)
|
||||
return
|
||||
}
|
||||
capa, err := models.GetCapabilities(ctx, userCred, query, nil)
|
||||
capa, err := models.GetCapabilities(ctx, userCred, query, nil, nil)
|
||||
if err != nil {
|
||||
httperrors.GeneralServerError(w, err)
|
||||
return
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package consts
|
||||
@@ -1 +0,0 @@
|
||||
package consts // import "yunion.io/x/onecloud/pkg/compute/consts"
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
@@ -36,6 +36,16 @@ func (self *SAliyunGuestDriver) GetMinimalSysDiskSizeGb() int {
|
||||
return 20
|
||||
}
|
||||
|
||||
func (self *SAliyunGuestDriver) GetStorageTypes() []string {
|
||||
return []string{
|
||||
models.STORAGE_CLOUD_EFFICIENCY,
|
||||
models.STORAGE_CLOUD_SSD,
|
||||
models.STORAGE_CLOUD_ESSD,
|
||||
models.STORAGE_PUBLIC_CLOUD,
|
||||
models.STORAGE_EPHEMERAL_SSD,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SAliyunGuestDriver) ChooseHostStorage(host *models.SHost, backend string) *models.SStorage {
|
||||
storages := host.GetAttachedStorages("")
|
||||
for i := 0; i < len(storages); i += 1 {
|
||||
@@ -43,13 +53,7 @@ func (self *SAliyunGuestDriver) ChooseHostStorage(host *models.SHost, backend st
|
||||
return &storages[i]
|
||||
}
|
||||
}
|
||||
for _, stype := range []string{
|
||||
models.STORAGE_CLOUD_EFFICIENCY,
|
||||
models.STORAGE_CLOUD_SSD,
|
||||
models.STORAGE_CLOUD_ESSD,
|
||||
models.STORAGE_PUBLIC_CLOUD,
|
||||
models.STORAGE_EPHEMERAL_SSD,
|
||||
} {
|
||||
for _, stype := range self.GetStorageTypes() {
|
||||
for i := 0; i < len(storages); i += 1 {
|
||||
if storages[i].StorageType == stype {
|
||||
return &storages[i]
|
||||
@@ -96,19 +100,15 @@ func (self *SAliyunGuestDriver) RequestDetachDisk(ctx context.Context, guest *mo
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SAliyunGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
data, err := self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, data)
|
||||
func (self *SAliyunGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
|
||||
input, err := self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if data.Contains("net.0") && data.Contains("net.1") {
|
||||
if len(input.Networks) > 2 {
|
||||
return nil, httperrors.NewInputParameterError("cannot support more than 1 nic")
|
||||
}
|
||||
for i := 0; data.Contains(fmt.Sprintf("disk.%d", i)); i++ {
|
||||
disk := models.SDiskConfig{}
|
||||
if err := data.Unmarshal(&disk, fmt.Sprintf("disk.%d", i)); err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid diskinfo of index %d", i)
|
||||
}
|
||||
for i, disk := range input.Disks {
|
||||
if i == 0 && (disk.SizeMb < 20*1024 || disk.SizeMb > 500*1024) {
|
||||
return nil, httperrors.NewInputParameterError("The system disk size must be in the range of 20GB ~ 500Gb")
|
||||
}
|
||||
@@ -127,7 +127,7 @@ func (self *SAliyunGuestDriver) ValidateCreateData(ctx context.Context, userCred
|
||||
}
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SAliyunGuestDriver) GetGuestInitialStateAfterCreate() string {
|
||||
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
@@ -69,6 +69,16 @@ func (self *SAwsGuestDriver) GetMinimalSysDiskSizeGb() int {
|
||||
return 10
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) GetStorageTypes() []string {
|
||||
return []string{
|
||||
models.STORAGE_GP2_SSD,
|
||||
models.STORAGE_IO1_SSD,
|
||||
models.STORAGE_ST1_HDD,
|
||||
models.STORAGE_SC1_HDD,
|
||||
models.STORAGE_STANDARD_HDD,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) ChooseHostStorage(host *models.SHost, backend string) *models.SStorage {
|
||||
storages := host.GetAttachedStorages("")
|
||||
for i := 0; i < len(storages); i += 1 {
|
||||
@@ -77,13 +87,7 @@ func (self *SAwsGuestDriver) ChooseHostStorage(host *models.SHost, backend strin
|
||||
}
|
||||
}
|
||||
|
||||
for _, stype := range []string{
|
||||
models.STORAGE_GP2_SSD,
|
||||
models.STORAGE_IO1_SSD,
|
||||
models.STORAGE_ST1_HDD,
|
||||
models.STORAGE_SC1_HDD,
|
||||
models.STORAGE_STANDARD_HDD,
|
||||
} {
|
||||
for _, stype := range self.GetStorageTypes() {
|
||||
for i := 0; i < len(storages); i += 1 {
|
||||
if storages[i].StorageType == stype {
|
||||
return &storages[i]
|
||||
@@ -117,8 +121,8 @@ func (self *SAwsGuestDriver) RequestDetachDisk(ctx context.Context, guest *model
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, data)
|
||||
func (self *SAwsGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
|
||||
return self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, input)
|
||||
}
|
||||
|
||||
func (self *SAwsGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *models.SDisk, storage *models.SStorage) error {
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/cmdline"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -40,6 +42,14 @@ func (self *SAzureGuestDriver) GetMinimalSysDiskSizeGb() int {
|
||||
return 10
|
||||
}
|
||||
|
||||
func (self *SAzureGuestDriver) GetStorageTypes() []string {
|
||||
return []string{
|
||||
models.STORAGE_STANDARD_LRS,
|
||||
models.STORAGE_STANDARDSSD_LRS,
|
||||
models.STORAGE_PREMIUM_LRS,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SAzureGuestDriver) ChooseHostStorage(host *models.SHost, backend string) *models.SStorage {
|
||||
storages := host.GetAttachedStorages("")
|
||||
for i := 0; i < len(storages); i += 1 {
|
||||
@@ -47,11 +57,7 @@ func (self *SAzureGuestDriver) ChooseHostStorage(host *models.SHost, backend str
|
||||
return &storages[i]
|
||||
}
|
||||
}
|
||||
for _, stype := range []string{
|
||||
models.STORAGE_STANDARD_LRS,
|
||||
models.STORAGE_STANDARDSSD_LRS,
|
||||
models.STORAGE_PREMIUM_LRS,
|
||||
} {
|
||||
for _, stype := range self.GetStorageTypes() {
|
||||
for i := 0; i < len(storages); i += 1 {
|
||||
if storages[i].StorageType == stype {
|
||||
return &storages[i]
|
||||
@@ -102,26 +108,30 @@ func (self *SAzureGuestDriver) RequestDetachDisk(ctx context.Context, guest *mod
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SAzureGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
data, err := self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, data)
|
||||
func (self *SAzureGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
|
||||
input, err := self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if data.Contains("net.0") && data.Contains("net.1") {
|
||||
if len(input.Networks) > 2 {
|
||||
return nil, httperrors.NewInputParameterError("cannot support more than 1 nic")
|
||||
}
|
||||
return data, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SAzureGuestDriver) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
data, err := self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, data)
|
||||
input, err := cmdline.FetchServerCreateInputByJSON(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if data.Contains("name") {
|
||||
input, err = self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if input.Name != "" {
|
||||
return nil, httperrors.NewInputParameterError("cannot support change azure instance name")
|
||||
}
|
||||
return data, nil
|
||||
return input.JSON(input), nil
|
||||
}
|
||||
|
||||
func (self *SAzureGuestDriver) GetGuestInitialStateAfterCreate() string {
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
@@ -55,32 +56,21 @@ func (self *SBaremetalGuestDriver) GetMaxVMemSizeGB() int {
|
||||
return 4096
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) PrepareDiskRaidConfig(userCred mcclient.TokenCredential, host *models.SHost, params *jsonutils.JSONDict) error {
|
||||
func (self *SBaremetalGuestDriver) PrepareDiskRaidConfig(userCred mcclient.TokenCredential, host *models.SHost, confs []*api.BaremetalDiskConfig) error {
|
||||
baremetalStorage := models.ConvertStorageInfo2BaremetalStorages(host.StorageInfo)
|
||||
if baremetalStorage == nil {
|
||||
return fmt.Errorf("Convert storage info error")
|
||||
}
|
||||
confs, err := params.GetArray("baremetal_disk_config")
|
||||
if err != nil {
|
||||
if len(confs) == 0 {
|
||||
parsedConf, _ := baremetal.ParseDiskConfig("")
|
||||
nConfs := []*baremetal.BaremetalDiskConfig{&parsedConf}
|
||||
nConfs := []*api.BaremetalDiskConfig{&parsedConf}
|
||||
layouts, err := baremetal.CalculateLayout(nConfs, baremetalStorage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return host.UpdateDiskConfig(userCred, layouts)
|
||||
} else {
|
||||
var nConfs = make([]*baremetal.BaremetalDiskConfig, 0)
|
||||
for i := 0; i < len(confs); i++ {
|
||||
parsedConf := &baremetal.BaremetalDiskConfig{}
|
||||
err := confs[i].Unmarshal(parsedConf)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
nConfs = append(nConfs, parsedConf)
|
||||
}
|
||||
layouts, err := baremetal.CalculateLayout(nConfs, baremetalStorage)
|
||||
layouts, err := baremetal.CalculateLayout(confs, baremetalStorage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -104,7 +94,7 @@ func (self *SBaremetalGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk
|
||||
return httperrors.NewUnsupportOperationError("Cannot resize disk for baremtal")
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) GetNamedNetworkConfiguration(guest *models.SGuest, userCred mcclient.TokenCredential, host *models.SHost, netConfig *models.SNetworkConfig) (*models.SNetwork, []models.SNicConfig, models.IPAddlocationDirection) {
|
||||
func (self *SBaremetalGuestDriver) GetNamedNetworkConfiguration(guest *models.SGuest, userCred mcclient.TokenCredential, host *models.SHost, netConfig *api.NetworkConfig) (*models.SNetwork, []models.SNicConfig, models.IPAddlocationDirection) {
|
||||
netifs, net := host.GetNetinterfacesWithIdAndCredential(netConfig.Network, userCred, netConfig.Reserved)
|
||||
if netifs != nil {
|
||||
nicCnt := 1
|
||||
@@ -135,7 +125,7 @@ func (self *SBaremetalGuestDriver) GetRandomNetworkTypes() []string {
|
||||
return []string{models.NETWORK_TYPE_BAREMETAL, models.NETWORK_TYPE_GUEST}
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) Attach2RandomNetwork(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, netConfig *models.SNetworkConfig, pendingUsage quotas.IQuota) ([]models.SGuestnetwork, error) {
|
||||
func (self *SBaremetalGuestDriver) Attach2RandomNetwork(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, netConfig *api.NetworkConfig, pendingUsage quotas.IQuota) ([]models.SGuestnetwork, error) {
|
||||
netifs := host.GetNetInterfaces()
|
||||
netsAvaiable := make([]models.SNetwork, 0)
|
||||
netifIndexs := make(map[string][]models.SNetInterface, 0)
|
||||
@@ -203,6 +193,10 @@ func (self *SBaremetalGuestDriver) Attach2RandomNetwork(guest *models.SGuest, ct
|
||||
return nil, fmt.Errorf("No appropriate host virtual network...")
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) GetStorageTypes() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) ChooseHostStorage(host *models.SHost, backend string) *models.SStorage {
|
||||
bs := host.GetBaremetalstorage()
|
||||
if bs == nil {
|
||||
@@ -298,35 +292,37 @@ func (self *SBaremetalGuestDriver) StartGuestSyncstatusTask(guest *models.SGuest
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
var confs = make([]baremetal.BaremetalDiskConfig, 0)
|
||||
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", i)
|
||||
}
|
||||
confs = append(confs, bmConf)
|
||||
}
|
||||
if len(confs) == 0 {
|
||||
bmConf, _ := baremetal.ParseDiskConfig("")
|
||||
confs = append(confs, bmConf)
|
||||
}
|
||||
data.Set("baremetal_disk_config", jsonutils.Marshal(confs))
|
||||
if !data.Contains("disk.0") {
|
||||
func (self *SBaremetalGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
|
||||
/*var confs = make([]api.BaremetalDiskConfig, 0)*/
|
||||
//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", i)
|
||||
//}
|
||||
//confs = append(confs, bmConf)
|
||||
//}
|
||||
//if len(confs) == 0 {
|
||||
//bmConf, _ := baremetal.ParseDiskConfig("")
|
||||
//confs = append(confs, bmConf)
|
||||
//}
|
||||
/*data.Set("baremetal_disk_config", jsonutils.Marshal(confs))*/
|
||||
if len(input.Disks) <= 0 {
|
||||
return nil, httperrors.NewInputParameterError("Root disk must be present")
|
||||
}
|
||||
disk0, _ := data.Get("disk.0")
|
||||
if !disk0.Contains("image_id") {
|
||||
|
||||
disk0 := input.Disks[0]
|
||||
|
||||
if disk0.ImageId == "" {
|
||||
return nil, httperrors.NewInputParameterError("Root disk must have templete")
|
||||
}
|
||||
return data, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) ValidateCreateHostData(ctx context.Context, userCred mcclient.TokenCredential, bmName string, host *models.SHost, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
func (self *SBaremetalGuestDriver) ValidateCreateHostData(ctx context.Context, userCred mcclient.TokenCredential, bmName string, host *models.SHost, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
|
||||
if host.HostType != models.HOST_TYPE_BAREMETAL || !host.IsBaremetal {
|
||||
return nil, httperrors.NewInputParameterError("Host %s is not a baremetal", bmName)
|
||||
}
|
||||
@@ -336,9 +332,9 @@ func (self *SBaremetalGuestDriver) ValidateCreateHostData(ctx context.Context, u
|
||||
if host.GetBaremetalServer() != nil {
|
||||
return nil, httperrors.NewInsufficientResourceError("Baremetal %s is occupied", bmName)
|
||||
}
|
||||
data.Set("vmem_size", jsonutils.NewInt(int64(host.MemSize)))
|
||||
data.Set("vcpu_count", jsonutils.NewInt(int64(host.CpuCount)))
|
||||
return data, nil
|
||||
input.VmemSize = host.MemSize
|
||||
input.VcpuCount = int(host.CpuCount)
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SBaremetalGuestDriver) GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost) jsonutils.JSONObject {
|
||||
|
||||
@@ -28,20 +28,6 @@ func init() {
|
||||
models.RegisterGuestDriver(&driver)
|
||||
}
|
||||
|
||||
func (self *SContainerDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
vmemSize, vcpuCount, err := models.ValidateMemCpuData(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if vmemSize > 0 {
|
||||
data.Add(jsonutils.NewInt(int64(vmemSize)), "vmem_size")
|
||||
}
|
||||
if vcpuCount > 0 {
|
||||
data.Add(jsonutils.NewInt(int64(vcpuCount)), "vcpu_count")
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (self *SContainerDriver) newUnsupportOperationError(option string) error {
|
||||
return httperrors.NewUnsupportOperationError("Container not support %s", option)
|
||||
}
|
||||
|
||||
@@ -4,13 +4,11 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"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/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/billing"
|
||||
)
|
||||
|
||||
@@ -35,6 +33,10 @@ func (self *SHuaweiGuestDriver) GetMinimalSysDiskSizeGb() int {
|
||||
return 10
|
||||
}
|
||||
|
||||
func (self *SHuaweiGuestDriver) GetStorageTypes() []string {
|
||||
return []string{models.STORAGE_HUAWEI_SATA, models.STORAGE_HUAWEI_SAS, models.STORAGE_HUAWEI_SSD}
|
||||
}
|
||||
|
||||
func (self *SHuaweiGuestDriver) ChooseHostStorage(host *models.SHost, backend string) *models.SStorage {
|
||||
storages := host.GetAttachedStorages("")
|
||||
for i := 0; i < len(storages); i += 1 {
|
||||
@@ -43,7 +45,7 @@ func (self *SHuaweiGuestDriver) ChooseHostStorage(host *models.SHost, backend st
|
||||
}
|
||||
}
|
||||
|
||||
for _, stype := range []string{models.STORAGE_HUAWEI_SATA, models.STORAGE_HUAWEI_SAS, models.STORAGE_HUAWEI_SSD} {
|
||||
for _, stype := range self.GetStorageTypes() {
|
||||
for i := 0; i < len(storages); i += 1 {
|
||||
if storages[i].StorageType == stype {
|
||||
return &storages[i]
|
||||
@@ -77,10 +79,6 @@ func (self *SHuaweiGuestDriver) RequestDetachDisk(ctx context.Context, guest *mo
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SHuaweiGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, data)
|
||||
}
|
||||
|
||||
func (self *SHuaweiGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *models.SDisk, storage *models.SStorage) error {
|
||||
if !utils.IsInStringArray(guest.Status, []string{models.VM_RUNNING, models.VM_READY}) {
|
||||
return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
@@ -348,7 +349,9 @@ func (self *SKVMGuestDriver) RqeuestSuspendOnHost(ctx context.Context, guest *mo
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) RequestGuestCreateAllDisks(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
|
||||
return guest.StartGuestCreateDiskTask(ctx, task.GetUserCred(), task.GetParams(), task.GetTaskId())
|
||||
input := new(api.ServerCreateInput)
|
||||
task.GetParams().Unmarshal(input)
|
||||
return guest.StartGuestCreateDiskTask(ctx, task.GetUserCred(), input.Disks, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, task taskman.ITask) error {
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -42,6 +43,10 @@ func (self *SOpenStackGuestDriver) GetMinimalSysDiskSizeGb() int {
|
||||
return options.Options.DefaultDiskSizeMB / 1024
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) GetStorageTypes() []string {
|
||||
return []string{models.STORAGE_OPENSTACK_ISCSI}
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) ChooseHostStorage(host *models.SHost, backend string) *models.SStorage {
|
||||
storages := host.GetAttachedStorages("")
|
||||
for i := 0; i < len(storages); i++ {
|
||||
@@ -49,7 +54,7 @@ func (self *SOpenStackGuestDriver) ChooseHostStorage(host *models.SHost, backend
|
||||
return &storages[i]
|
||||
}
|
||||
}
|
||||
for _, stype := range []string{models.STORAGE_OPENSTACK_ISCSI} {
|
||||
for _, stype := range self.GetStorageTypes() {
|
||||
for i := 0; i < len(storages); i++ {
|
||||
if storages[i].StorageType == stype {
|
||||
return &storages[i]
|
||||
@@ -83,15 +88,16 @@ func (self *SOpenStackGuestDriver) GetDeployStatus() ([]string, error) {
|
||||
return []string{models.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
data, err := self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, data)
|
||||
func (self *SOpenStackGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
|
||||
var err error
|
||||
input, err = self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if data.Contains("net.0") && data.Contains("net.1") {
|
||||
if len(input.Networks) >= 2 {
|
||||
return nil, httperrors.NewInputParameterError("cannot support more than 1 nic")
|
||||
}
|
||||
return data, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SOpenStackGuestDriver) GetGuestInitialStateAfterCreate() string {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -38,6 +39,16 @@ func (self *SQcloudGuestDriver) GetMinimalSysDiskSizeGb() int {
|
||||
return 50
|
||||
}
|
||||
|
||||
func (self *SQcloudGuestDriver) GetStorageTypes() []string {
|
||||
return []string{
|
||||
models.STORAGE_CLOUD_BASIC,
|
||||
models.STORAGE_CLOUD_PREMIUM,
|
||||
models.STORAGE_CLOUD_SSD,
|
||||
models.STORAGE_LOCAL_BASIC,
|
||||
models.STORAGE_LOCAL_SSD,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SQcloudGuestDriver) ChooseHostStorage(host *models.SHost, backend string) *models.SStorage {
|
||||
storages := host.GetAttachedStorages("")
|
||||
for i := 0; i < len(storages); i++ {
|
||||
@@ -45,13 +56,7 @@ func (self *SQcloudGuestDriver) ChooseHostStorage(host *models.SHost, backend st
|
||||
return &storages[i]
|
||||
}
|
||||
}
|
||||
for _, stype := range []string{
|
||||
models.STORAGE_CLOUD_BASIC,
|
||||
models.STORAGE_CLOUD_PREMIUM,
|
||||
models.STORAGE_CLOUD_SSD,
|
||||
models.STORAGE_LOCAL_BASIC,
|
||||
models.STORAGE_LOCAL_SSD,
|
||||
} {
|
||||
for _, stype := range self.GetStorageTypes() {
|
||||
for i := 0; i < len(storages); i++ {
|
||||
if storages[i].StorageType == stype {
|
||||
return &storages[i]
|
||||
@@ -99,18 +104,16 @@ func (self *SQcloudGuestDriver) RequestDetachDisk(ctx context.Context, guest *mo
|
||||
return guest.StartSyncTask(ctx, task.GetUserCred(), false, task.GetTaskId())
|
||||
}
|
||||
|
||||
func (self *SQcloudGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
data, err := self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, data)
|
||||
func (self *SQcloudGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
|
||||
input, err := self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if data.Contains("net.0") && data.Contains("net.1") {
|
||||
if len(input.Networks) > 2 {
|
||||
return nil, httperrors.NewInputParameterError("cannot support more than 1 nic")
|
||||
}
|
||||
sysDisk := models.SDiskConfig{}
|
||||
if err := data.Unmarshal(&sysDisk, "disk.0"); err != nil {
|
||||
return nil, fmt.Errorf("Missing system disk information")
|
||||
}
|
||||
|
||||
sysDisk := input.Disks[0]
|
||||
switch sysDisk.Backend {
|
||||
case models.STORAGE_CLOUD_BASIC, models.STORAGE_CLOUD_SSD:
|
||||
if sysDisk.SizeMb > 500*1024 {
|
||||
@@ -122,11 +125,8 @@ func (self *SQcloudGuestDriver) ValidateCreateData(ctx context.Context, userCred
|
||||
}
|
||||
}
|
||||
|
||||
for i := 1; data.Contains(fmt.Sprintf("disk.%d", i)); i++ {
|
||||
disk := models.SDiskConfig{}
|
||||
if err := data.Unmarshal(&disk, fmt.Sprintf("disk.%d", i)); err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid diskinfo of index %d", i)
|
||||
}
|
||||
for i := 1; i < len(input.Disks); i++ {
|
||||
disk := input.Disks[i]
|
||||
switch disk.Backend {
|
||||
case models.STORAGE_CLOUD_BASIC:
|
||||
if disk.SizeMb < 10*1024 || disk.SizeMb > 16000*1024 {
|
||||
@@ -142,7 +142,7 @@ func (self *SQcloudGuestDriver) ValidateCreateData(ctx context.Context, userCred
|
||||
}
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SQcloudGuestDriver) GetGuestInitialStateAfterCreate() string {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
@@ -27,12 +28,12 @@ func (self *SVirtualizedGuestDriver) GetMaxVMemSizeGB() int {
|
||||
return 512
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) PrepareDiskRaidConfig(userCred mcclient.TokenCredential, host *models.SHost, params *jsonutils.JSONDict) error {
|
||||
func (self *SVirtualizedGuestDriver) PrepareDiskRaidConfig(userCred mcclient.TokenCredential, host *models.SHost, params []*api.BaremetalDiskConfig) error {
|
||||
// do nothing
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) GetNamedNetworkConfiguration(guest *models.SGuest, userCred mcclient.TokenCredential, host *models.SHost, netConfig *models.SNetworkConfig) (*models.SNetwork, []models.SNicConfig, models.IPAddlocationDirection) {
|
||||
func (self *SVirtualizedGuestDriver) GetNamedNetworkConfiguration(guest *models.SGuest, userCred mcclient.TokenCredential, host *models.SHost, netConfig *api.NetworkConfig) (*models.SNetwork, []models.SNicConfig, models.IPAddlocationDirection) {
|
||||
net, _ := host.GetNetworkWithIdAndCredential(netConfig.Network, userCred, netConfig.Reserved)
|
||||
nicConfs := []models.SNicConfig{
|
||||
{
|
||||
@@ -55,7 +56,7 @@ func (self *SVirtualizedGuestDriver) GetRandomNetworkTypes() []string {
|
||||
return []string{models.NETWORK_TYPE_GUEST}
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) Attach2RandomNetwork(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, netConfig *models.SNetworkConfig, pendingUsage quotas.IQuota) ([]models.SGuestnetwork, error) {
|
||||
func (self *SVirtualizedGuestDriver) Attach2RandomNetwork(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, netConfig *api.NetworkConfig, pendingUsage quotas.IQuota) ([]models.SGuestnetwork, error) {
|
||||
var wirePattern *regexp.Regexp
|
||||
if len(netConfig.Wire) > 0 {
|
||||
wirePattern = regexp.MustCompile(netConfig.Wire)
|
||||
@@ -115,6 +116,10 @@ func (self *SVirtualizedGuestDriver) Attach2RandomNetwork(guest *models.SGuest,
|
||||
return gn, err
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) GetStorageTypes() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) ChooseHostStorage(host *models.SHost, backend string) *models.SStorage {
|
||||
return host.GetLeastUsedStorage(backend)
|
||||
}
|
||||
@@ -183,24 +188,24 @@ func (self *SVirtualizedGuestDriver) RequestStopGuestForDelete(ctx context.Conte
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return data, nil
|
||||
func (self *SVirtualizedGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) ValidateCreateHostData(ctx context.Context, userCred mcclient.TokenCredential, bmName string, host *models.SHost, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
func (self *SVirtualizedGuestDriver) ValidateCreateHostData(ctx context.Context, userCred mcclient.TokenCredential, bmName string, host *models.SHost, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
|
||||
if host.HostStatus != models.HOST_ONLINE {
|
||||
return nil, httperrors.NewInvalidStatusError("Host %s is not online", bmName)
|
||||
}
|
||||
data.Add(jsonutils.NewString(host.Id), "prefer_host_id")
|
||||
input.PreferHost = host.Id
|
||||
if host.IsPrepaidRecycle() {
|
||||
data.Set("vmem_size", jsonutils.NewInt(int64(host.MemSize)))
|
||||
data.Set("vcpu_count", jsonutils.NewInt(int64(host.CpuCount)))
|
||||
input.VmemSize = host.MemSize
|
||||
input.VcpuCount = int(host.CpuCount)
|
||||
|
||||
if host.GetGuestCount() >= 1 {
|
||||
return nil, httperrors.NewInsufficientResourceError("host has been occupied")
|
||||
}
|
||||
}
|
||||
return data, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SVirtualizedGuestDriver) PerformStart(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, data *jsonutils.JSONDict) error {
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/compute/baremetal"
|
||||
@@ -156,17 +157,17 @@ func (self *SBaseHostDriver) GetRaidScheme(host *models.SHost, raid string) (str
|
||||
candidates = []string{raid}
|
||||
}
|
||||
}
|
||||
var conf []*baremetal.BaremetalDiskConfig
|
||||
var conf []*api.BaremetalDiskConfig
|
||||
for i := 0; i < len(candidates); i++ {
|
||||
if candidates[i] == baremetal.DISK_CONF_NONE {
|
||||
conf = []*baremetal.BaremetalDiskConfig{}
|
||||
conf = []*api.BaremetalDiskConfig{}
|
||||
} else {
|
||||
parsedConf, err := baremetal.ParseDiskConfig(candidates[i])
|
||||
if err != nil {
|
||||
log.Errorf("try raid %s failed: %s", candidates[i], err.Error())
|
||||
return "", err
|
||||
}
|
||||
conf = []*baremetal.BaremetalDiskConfig{&parsedConf}
|
||||
conf = []*api.BaremetalDiskConfig{&parsedConf}
|
||||
}
|
||||
baremetalStorage := models.ConvertStorageInfo2BaremetalStorages(host.StorageInfo)
|
||||
if baremetalStorage == nil {
|
||||
|
||||
@@ -341,6 +341,7 @@ func (self *SKVMHostDriver) PrepareConvert(host *models.SHost, image, raid strin
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: use api.ServerCreateInput
|
||||
var sysSize = "60g"
|
||||
if data.Contains("baremetal_disk_config.0") {
|
||||
jsonArray := jsonutils.GetArrayOfPrefix(data, "baremetal_disk_config")
|
||||
|
||||
@@ -236,18 +236,7 @@ func (self *SManagedVirtualizationHostDriver) RequestAllocateDiskOnStorage(ctx c
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if metaData := iDisk.GetMetadata(); metaData != nil {
|
||||
meta := make(map[string]string)
|
||||
if err := metaData.Unmarshal(meta); err != nil {
|
||||
log.Errorf("Get disk %s Metadata error: %v", disk.Name, err)
|
||||
} else {
|
||||
for key, value := range meta {
|
||||
if err := disk.SetMetadata(ctx, key, value, task.GetUserCred()); err != nil {
|
||||
log.Errorf("set disk %s mata %s => %s error: %v", disk.Name, key, value, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
models.SyncMetadata(ctx, task.GetUserCred(), disk, iDisk)
|
||||
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewInt(int64(iDisk.GetDiskSizeMB())), "disk_size")
|
||||
|
||||
@@ -25,23 +25,26 @@ type SCapabilities struct {
|
||||
Specs jsonutils.JSONObject
|
||||
}
|
||||
|
||||
func GetCapabilities(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, zone *SZone) (SCapabilities, error) {
|
||||
func GetCapabilities(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, region *SCloudregion, zone *SZone) (SCapabilities, error) {
|
||||
capa := SCapabilities{}
|
||||
capa.Hypervisors = getHypervisors(zone)
|
||||
capa.ResourceTypes = getResourceTypes(zone)
|
||||
capa.StorageTypes = getStorageTypes(zone, true)
|
||||
capa.DataStorageTypes = getStorageTypes(zone, false)
|
||||
capa.GPUModels = getGPUs(zone)
|
||||
capa.SchedPolicySupport = isSchedPolicySupported(zone)
|
||||
capa.MinNicCount = getMinNicCount(zone)
|
||||
capa.MaxNicCount = getMaxNicCount(zone)
|
||||
capa.MinDataDiskCount = getMinDataDiskCount(zone)
|
||||
capa.MaxDataDiskCount = getMaxDataDiskCount(zone)
|
||||
capa.Usable = isUsable(zone)
|
||||
capa.Hypervisors = getHypervisors(region, zone)
|
||||
capa.ResourceTypes = getResourceTypes(region, zone)
|
||||
capa.StorageTypes = getStorageTypes(region, zone, true)
|
||||
capa.DataStorageTypes = getStorageTypes(region, zone, false)
|
||||
capa.GPUModels = getGPUs(region, zone)
|
||||
capa.SchedPolicySupport = isSchedPolicySupported(region, zone)
|
||||
capa.MinNicCount = getMinNicCount(region, zone)
|
||||
capa.MaxNicCount = getMaxNicCount(region, zone)
|
||||
capa.MinDataDiskCount = getMinDataDiskCount(region, zone)
|
||||
capa.MaxDataDiskCount = getMaxDataDiskCount(region, zone)
|
||||
capa.Usable = isUsable(region, zone)
|
||||
if query == nil {
|
||||
query = jsonutils.NewDict()
|
||||
}
|
||||
var err error
|
||||
if region != nil {
|
||||
query.(*jsonutils.JSONDict).Add(jsonutils.NewString(region.GetId()), "region")
|
||||
}
|
||||
if zone != nil {
|
||||
query.(*jsonutils.JSONDict).Add(jsonutils.NewString(zone.GetId()), "zone")
|
||||
}
|
||||
@@ -50,8 +53,16 @@ func GetCapabilities(ctx context.Context, userCred mcclient.TokenCredential, que
|
||||
return capa, err
|
||||
}
|
||||
|
||||
func getHypervisors(zone *SZone) []string {
|
||||
func getRegionZoneSubq(region *SCloudregion) *sqlchemy.SSubQuery {
|
||||
return ZoneManager.Query("id").Equals("cloudregion_id", region.GetId()).SubQuery()
|
||||
}
|
||||
|
||||
func getHypervisors(region *SCloudregion, zone *SZone) []string {
|
||||
q := HostManager.Query("host_type")
|
||||
if region != nil {
|
||||
subq := getRegionZoneSubq(region)
|
||||
q = q.Filter(sqlchemy.In(q.Field("zone_id"), subq))
|
||||
}
|
||||
if zone != nil {
|
||||
q = q.Equals("zone_id", zone.Id)
|
||||
}
|
||||
@@ -75,8 +86,12 @@ func getHypervisors(zone *SZone) []string {
|
||||
return hypervisors
|
||||
}
|
||||
|
||||
func getResourceTypes(zone *SZone) []string {
|
||||
func getResourceTypes(region *SCloudregion, zone *SZone) []string {
|
||||
q := HostManager.Query("resource_type")
|
||||
if region != nil {
|
||||
subq := getRegionZoneSubq(region)
|
||||
q = q.Filter(sqlchemy.In(q.Field("zone_id"), subq))
|
||||
}
|
||||
if zone != nil {
|
||||
q = q.Equals("zone_id", zone.Id)
|
||||
}
|
||||
@@ -99,7 +114,7 @@ func getResourceTypes(zone *SZone) []string {
|
||||
return resourceTypes
|
||||
}
|
||||
|
||||
func getStorageTypes(zone *SZone, isSysDisk bool) []string {
|
||||
func getStorageTypes(region *SCloudregion, zone *SZone, isSysDisk bool) []string {
|
||||
storages := StorageManager.Query().SubQuery()
|
||||
hostStorages := HoststorageManager.Query().SubQuery()
|
||||
hosts := HostManager.Query().SubQuery()
|
||||
@@ -113,6 +128,10 @@ func getStorageTypes(zone *SZone, isSysDisk bool) []string {
|
||||
hosts.Field("id"),
|
||||
hostStorages.Field("host_id"),
|
||||
))
|
||||
if region != nil {
|
||||
subq := getRegionZoneSubq(region)
|
||||
q = q.Filter(sqlchemy.In(storages.Field("zone_id"), subq))
|
||||
}
|
||||
if zone != nil {
|
||||
q = q.Filter(sqlchemy.Equals(storages.Field("zone_id"), zone.Id))
|
||||
}
|
||||
@@ -144,11 +163,16 @@ func getStorageTypes(zone *SZone, isSysDisk bool) []string {
|
||||
return storageTypes
|
||||
}
|
||||
|
||||
func getGPUs(zone *SZone) []string {
|
||||
func getGPUs(region *SCloudregion, zone *SZone) []string {
|
||||
devices := IsolatedDeviceManager.Query().SubQuery()
|
||||
hosts := HostManager.Query().SubQuery()
|
||||
|
||||
q := devices.Query(devices.Field("model"))
|
||||
if region != nil {
|
||||
subq := getRegionZoneSubq(region)
|
||||
q = q.Join(hosts, sqlchemy.Equals(devices.Field("host_id"), hosts.Field("id")))
|
||||
q = q.Filter(sqlchemy.In(hosts.Field("zone_id"), subq))
|
||||
}
|
||||
if zone != nil {
|
||||
q = q.Join(hosts, sqlchemy.Equals(devices.Field("host_id"), hosts.Field("id")))
|
||||
q = q.Filter(sqlchemy.Equals(hosts.Field("zone_id"), zone.Id))
|
||||
@@ -171,12 +195,17 @@ func getGPUs(zone *SZone) []string {
|
||||
return gpus
|
||||
}
|
||||
|
||||
func getNetworkCount(zone *SZone) int {
|
||||
func getNetworkCount(region *SCloudregion, zone *SZone) int {
|
||||
wires := WireManager.Query().SubQuery()
|
||||
networks := NetworkManager.Query().SubQuery()
|
||||
|
||||
q := networks.Query()
|
||||
if region != nil {
|
||||
subq := getRegionZoneSubq(region)
|
||||
q = q.Join(wires, sqlchemy.Equals(networks.Field("wire_id"), wires.Field("id")))
|
||||
q = q.Filter(sqlchemy.In(wires.Field("zone_id"), subq))
|
||||
}
|
||||
if zone != nil {
|
||||
wires := WireManager.Query().SubQuery()
|
||||
q = q.Join(wires, sqlchemy.Equals(networks.Field("wire_id"), wires.Field("id")))
|
||||
q = q.Filter(sqlchemy.Equals(wires.Field("zone_id"), zone.Id))
|
||||
}
|
||||
@@ -185,44 +214,52 @@ func getNetworkCount(zone *SZone) int {
|
||||
return q.Count()
|
||||
}
|
||||
|
||||
func isSchedPolicySupported(zone *SZone) bool {
|
||||
func isSchedPolicySupported(region *SCloudregion, zone *SZone) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func getMinNicCount(zone *SZone) int {
|
||||
func getMinNicCount(region *SCloudregion, zone *SZone) int {
|
||||
if region != nil {
|
||||
return region.getMinNicCount()
|
||||
}
|
||||
if zone != nil {
|
||||
return zone.getMinNicCount()
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func getMaxNicCount(zone *SZone) int {
|
||||
func getMaxNicCount(region *SCloudregion, zone *SZone) int {
|
||||
if region != nil {
|
||||
return region.getMaxNicCount()
|
||||
}
|
||||
if zone != nil {
|
||||
return zone.getMaxNicCount()
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func getMinDataDiskCount(zone *SZone) int {
|
||||
func getMinDataDiskCount(region *SCloudregion, zone *SZone) int {
|
||||
if region != nil {
|
||||
return region.getMinDataDiskCount()
|
||||
}
|
||||
if zone != nil {
|
||||
return zone.getMinDataDiskCount()
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func getMaxDataDiskCount(zone *SZone) int {
|
||||
func getMaxDataDiskCount(region *SCloudregion, zone *SZone) int {
|
||||
if region != nil {
|
||||
return region.getMaxDataDiskCount()
|
||||
}
|
||||
if zone != nil {
|
||||
return zone.getMaxDataDiskCount()
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func isUsable(zone *SZone) bool {
|
||||
if getNetworkCount(zone) > 0 {
|
||||
func isUsable(region *SCloudregion, zone *SZone) bool {
|
||||
if getNetworkCount(region, zone) > 0 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
||||
@@ -429,7 +429,24 @@ func (self *SCloudaccount) MarkSyncing(userCred mcclient.TokenCredential) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) MarkEndSync(userCred mcclient.TokenCredential) error {
|
||||
func (self *SCloudaccount) MarkEndSyncWithLock(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
lockman.LockObject(ctx, self)
|
||||
defer lockman.ReleaseObject(ctx, self)
|
||||
|
||||
if self.SyncStatus == CLOUD_PROVIDER_SYNC_STATUS_IDLE {
|
||||
return nil
|
||||
}
|
||||
|
||||
providers := self.GetCloudproviders()
|
||||
for i := range providers {
|
||||
if providers[i].SyncStatus != CLOUD_PROVIDER_SYNC_STATUS_IDLE {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return self.markEndSync(userCred)
|
||||
}
|
||||
|
||||
func (self *SCloudaccount) markEndSync(userCred mcclient.TokenCredential) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.SyncStatus = CLOUD_PROVIDER_SYNC_STATUS_IDLE
|
||||
self.LastSyncEndAt = timeutils.UtcNow()
|
||||
@@ -895,7 +912,7 @@ func (manager *SCloudaccountManager) ListItemFilter(ctx context.Context, q *sqlc
|
||||
}
|
||||
|
||||
if jsonutils.QueryBoolean(query, "private_cloud", false) {
|
||||
q = q.IsFalse("is_public_cloud")
|
||||
q = q.IsFalse("is_public_cloud").IsFalse("is_on_premise")
|
||||
}
|
||||
|
||||
if jsonutils.QueryBoolean(query, "is_on_premise", false) {
|
||||
@@ -1125,8 +1142,8 @@ func (account *SCloudaccount) syncAccountStatus(ctx context.Context, userCred mc
|
||||
account.MarkSyncing(userCred)
|
||||
subaccounts, err := account.probeAccountStatus(ctx, userCred)
|
||||
if err != nil {
|
||||
account.markAccountDiscconected(ctx, userCred)
|
||||
account.markAllProvidersDicconnected(ctx, userCred)
|
||||
account.markAccountDiscconected(ctx, userCred)
|
||||
return err
|
||||
}
|
||||
account.markAccountConnected(ctx, userCred)
|
||||
@@ -1146,16 +1163,23 @@ func (account *SCloudaccount) SubmitSyncAccountTask(ctx context.Context, userCre
|
||||
log.Debugf("syncAccountStatus %s %s", account.Id, account.Name)
|
||||
err := account.syncAccountStatus(ctx, userCred)
|
||||
if waitChan != nil {
|
||||
if err != nil {
|
||||
account.markEndSync(userCred)
|
||||
}
|
||||
waitChan <- err
|
||||
} else {
|
||||
syncCnt := 0
|
||||
if err == nil && autoSync && account.Enabled && account.EnableAutoSync {
|
||||
syncRange := SSyncRange{FullSync: true}
|
||||
providers := account.GetEnabledCloudproviders()
|
||||
for i := range providers {
|
||||
providers[i].syncCloudproviderRegions(userCred, &syncRange, nil)
|
||||
providers[i].syncCloudproviderRegions(ctx, userCred, &syncRange, nil, autoSync)
|
||||
syncCnt += 1
|
||||
}
|
||||
}
|
||||
account.MarkEndSync(userCred)
|
||||
if syncCnt == 0 {
|
||||
account.markEndSync(userCred)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -199,7 +199,19 @@ func (self *SCloudproviderregion) markSyncing(userCred mcclient.TokenCredential)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudproviderregion) markEndSync(userCred mcclient.TokenCredential, syncResults SSyncResultSet) error {
|
||||
func (self *SCloudproviderregion) markEndSync(ctx context.Context, userCred mcclient.TokenCredential, syncResults SSyncResultSet) error {
|
||||
err := self.markEndSyncInternal(userCred, syncResults)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = self.GetProvider().markEndSyncWithLock(ctx, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudproviderregion) markEndSyncInternal(userCred mcclient.TokenCredential, syncResults SSyncResultSet) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.SyncStatus = CLOUD_PROVIDER_SYNC_STATUS_IDLE
|
||||
self.LastSyncEndAt = timeutils.UtcNow()
|
||||
@@ -230,11 +242,10 @@ func (set SSyncResultSet) Add(manager db.IModelManager, result compare.SyncResul
|
||||
}
|
||||
|
||||
func (self *SCloudproviderregion) DoSync(ctx context.Context, userCred mcclient.TokenCredential, syncRange *SSyncRange) error {
|
||||
err := self.markSyncing(userCred)
|
||||
if err != nil {
|
||||
log.Errorf("start sync sql fail?? %s", err)
|
||||
return err
|
||||
}
|
||||
syncResults := SSyncResultSet{}
|
||||
|
||||
self.markSyncing(userCred)
|
||||
defer self.markEndSync(ctx, userCred, syncResults)
|
||||
|
||||
localRegion := self.GetRegion()
|
||||
provider := self.GetProvider()
|
||||
@@ -244,8 +255,6 @@ func (self *SCloudproviderregion) DoSync(ctx context.Context, userCred mcclient.
|
||||
return err
|
||||
}
|
||||
|
||||
syncResults := SSyncResultSet{}
|
||||
|
||||
if localRegion.isManaged() {
|
||||
remoteRegion, err := driver.GetIRegionById(localRegion.ExternalId)
|
||||
if err == nil {
|
||||
@@ -255,14 +264,13 @@ func (self *SCloudproviderregion) DoSync(ctx context.Context, userCred mcclient.
|
||||
err = syncOnPremiseCloudProviderInfo(ctx, userCred, syncResults, provider, driver, syncRange)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("dosync fail %s", err)
|
||||
}
|
||||
|
||||
log.Debugf("%s", jsonutils.Marshal(syncResults))
|
||||
|
||||
err = self.markEndSync(userCred, syncResults)
|
||||
if err != nil {
|
||||
log.Errorf("mark end sync failed...")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SCloudproviderregion) getSyncTaskKey() string {
|
||||
@@ -284,7 +292,7 @@ func (self *SCloudproviderregion) submitSyncTask(userCred mcclient.TokenCredenti
|
||||
})
|
||||
}
|
||||
|
||||
func (cpr *SCloudproviderregion) needSync() bool {
|
||||
func (cpr *SCloudproviderregion) needAutoSync() bool {
|
||||
if cpr.LastSyncEndAt.IsZero() {
|
||||
return true
|
||||
}
|
||||
@@ -297,7 +305,10 @@ func (cpr *SCloudproviderregion) needSync() bool {
|
||||
isEmpty = cpr.isEmptyPublicCloud()
|
||||
}
|
||||
if isEmpty {
|
||||
intval = intval * 16 // no need to check empty region
|
||||
intval = intval * 16 // no need to check empty region
|
||||
if intval > 24*3600 { // at least once everyday
|
||||
intval = 24 * 3600
|
||||
}
|
||||
region := cpr.GetRegion()
|
||||
log.Debugf("empty region %s! no need to check so frequently", region.GetName())
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
"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/options"
|
||||
@@ -527,7 +528,7 @@ func (self *SCloudprovider) markStartSync(userCred mcclient.TokenCredential) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudprovider) MarkSyncing(userCred mcclient.TokenCredential) error {
|
||||
func (self *SCloudprovider) markSyncing(userCred mcclient.TokenCredential) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.SyncStatus = CLOUD_PROVIDER_SYNC_STATUS_SYNCING
|
||||
self.LastSync = timeutils.UtcNow()
|
||||
@@ -541,7 +542,34 @@ func (self *SCloudprovider) MarkSyncing(userCred mcclient.TokenCredential) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SCloudprovider) MarkEndSync(userCred mcclient.TokenCredential) error {
|
||||
func (self *SCloudprovider) markEndSyncWithLock(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
err := func() error {
|
||||
lockman.LockObject(ctx, self)
|
||||
defer lockman.ReleaseObject(ctx, self)
|
||||
|
||||
cprs := self.GetCloudproviderRegions()
|
||||
for i := range cprs {
|
||||
if cprs[i].SyncStatus != CLOUD_PROVIDER_SYNC_STATUS_IDLE {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
err := self.markEndSync(userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
account := self.GetCloudaccount()
|
||||
return account.MarkEndSyncWithLock(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SCloudprovider) markEndSync(userCred mcclient.TokenCredential) error {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.SyncStatus = CLOUD_PROVIDER_SYNC_STATUS_IDLE
|
||||
self.LastSyncEndAt = timeutils.UtcNow()
|
||||
@@ -814,6 +842,7 @@ func (manager *SCloudproviderManager) ListItemFilter(ctx context.Context, q *sql
|
||||
cloudaccounts := CloudaccountManager.Query().SubQuery()
|
||||
q = q.Join(cloudaccounts, sqlchemy.Equals(cloudaccounts.Field("id"), q.Field("cloudaccount_id")))
|
||||
q = q.Filter(sqlchemy.IsFalse(cloudaccounts.Field("is_public_cloud")))
|
||||
q = q.Filter(sqlchemy.IsFalse(cloudaccounts.Field("is_on_premise")))
|
||||
}
|
||||
|
||||
if jsonutils.QueryBoolean(query, "is_on_premise", false) {
|
||||
@@ -859,19 +888,22 @@ func (provider *SCloudprovider) prepareCloudproviderRegions(ctx context.Context,
|
||||
return cprs, nil
|
||||
}
|
||||
|
||||
func (provider *SCloudprovider) GetEnabledCloudproviderRegions() []SCloudproviderregion {
|
||||
func (provider *SCloudprovider) GetCloudproviderRegions() []SCloudproviderregion {
|
||||
q := CloudproviderRegionManager.Query()
|
||||
q = q.IsTrue("enabled")
|
||||
q = q.Equals("cloudprovider_id", provider.Id)
|
||||
q = q.Equals("sync_status", CLOUD_PROVIDER_SYNC_STATUS_IDLE)
|
||||
// q = q.IsTrue("enabled")
|
||||
// q = q.Equals("sync_status", CLOUD_PROVIDER_SYNC_STATUS_IDLE)
|
||||
|
||||
return CloudproviderRegionManager.fetchRecordsByQuery(q)
|
||||
}
|
||||
|
||||
func (provider *SCloudprovider) syncCloudproviderRegions(userCred mcclient.TokenCredential, syncRange *SSyncRange, wg *sync.WaitGroup) {
|
||||
cprs := provider.GetEnabledCloudproviderRegions()
|
||||
func (provider *SCloudprovider) syncCloudproviderRegions(ctx context.Context, userCred mcclient.TokenCredential, syncRange *SSyncRange, wg *sync.WaitGroup, autoSync bool) {
|
||||
provider.markSyncing(userCred)
|
||||
cprs := provider.GetCloudproviderRegions()
|
||||
syncCnt := 0
|
||||
for i := range cprs {
|
||||
if cprs[i].needSync() {
|
||||
if cprs[i].Enabled && cprs[i].CanSync() && (!autoSync || cprs[i].needAutoSync()) {
|
||||
syncCnt += 1
|
||||
var waitChan chan bool = nil
|
||||
if wg != nil {
|
||||
wg.Add(1)
|
||||
@@ -884,11 +916,14 @@ func (provider *SCloudprovider) syncCloudproviderRegions(userCred mcclient.Token
|
||||
}
|
||||
}
|
||||
}
|
||||
if syncCnt == 0 {
|
||||
provider.markEndSyncWithLock(ctx, userCred)
|
||||
}
|
||||
}
|
||||
|
||||
func (provider *SCloudprovider) SyncCallSyncCloudproviderRegions(userCred mcclient.TokenCredential, syncRange *SSyncRange) {
|
||||
func (provider *SCloudprovider) SyncCallSyncCloudproviderRegions(ctx context.Context, userCred mcclient.TokenCredential, syncRange *SSyncRange) {
|
||||
var wg sync.WaitGroup
|
||||
provider.syncCloudproviderRegions(userCred, syncRange, &wg)
|
||||
provider.syncCloudproviderRegions(ctx, userCred, syncRange, &wg, false)
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"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/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
@@ -511,3 +512,38 @@ func (self *SCloudregion) ValidateUpdateCondition(ctx context.Context) error {
|
||||
}
|
||||
return self.SEnabledStatusStandaloneResourceBase.ValidateUpdateCondition(ctx)
|
||||
}
|
||||
|
||||
func (self *SCloudregion) AllowGetDetailsCapability(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SCloudregion) GetDetailsCapability(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
capa, err := GetCapabilities(ctx, userCred, query, self, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return jsonutils.Marshal(&capa), nil
|
||||
}
|
||||
|
||||
func (self *SCloudregion) getNetworkCount() int {
|
||||
return getNetworkCount(self, nil)
|
||||
}
|
||||
|
||||
func (self *SCloudregion) getMinNicCount() int {
|
||||
return options.Options.MinNicCount
|
||||
}
|
||||
|
||||
func (self *SCloudregion) getMaxNicCount() int {
|
||||
if self.isManaged() {
|
||||
return options.Options.MaxManagedNicCount
|
||||
}
|
||||
return options.Options.MaxNormalNicCount
|
||||
}
|
||||
|
||||
func (self *SCloudregion) getMinDataDiskCount() int {
|
||||
return options.Options.MinDataDiskCount
|
||||
}
|
||||
|
||||
func (self *SCloudregion) getMaxDataDiskCount() int {
|
||||
return options.Options.MaxDataDiskCount
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ type SSyncableBaseResource struct {
|
||||
|
||||
func (self *SSyncableBaseResource) CanSync() bool {
|
||||
if self.SyncStatus == CLOUD_PROVIDER_SYNC_STATUS_QUEUED || self.SyncStatus == CLOUD_PROVIDER_SYNC_STATUS_SYNCING {
|
||||
if self.LastSync.IsZero() || time.Now().Sub(self.LastSync) > 900*time.Second {
|
||||
if self.LastSync.IsZero() || time.Now().Sub(self.LastSync) > 1800*time.Second {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
||||
+102
-129
@@ -13,12 +13,12 @@ import (
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/util/fileutils"
|
||||
"yunion.io/x/pkg/util/osprofile"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
"yunion.io/x/pkg/util/timeutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/cmdline"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
@@ -33,42 +33,42 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
DISK_INIT = "init"
|
||||
DISK_REBUILD = "rebuild"
|
||||
DISK_ALLOC_FAILED = "alloc_failed"
|
||||
DISK_STARTALLOC = "start_alloc"
|
||||
DISK_BACKUP_STARTALLOC = "backup_start_alloc"
|
||||
DISK_BACKUP_ALLOC_FAILED = "backup_alloc_failed"
|
||||
DISK_ALLOCATING = "allocating"
|
||||
DISK_READY = "ready"
|
||||
DISK_RESET = "reset" // 快照回滚
|
||||
DISK_RESET_FAILED = "reset_failed" // 快照回滚失败
|
||||
DISK_DEALLOC = "deallocating"
|
||||
DISK_DEALLOC_FAILED = "dealloc_failed"
|
||||
DISK_UNKNOWN = "unknown"
|
||||
DISK_DETACHING = "detaching"
|
||||
DISK_ATTACHING = "attaching"
|
||||
DISK_CLONING = "cloning" // 硬盘克隆
|
||||
DISK_INIT = api.DISK_INIT
|
||||
DISK_REBUILD = api.DISK_REBUILD
|
||||
DISK_ALLOC_FAILED = api.DISK_ALLOC_FAILED
|
||||
DISK_STARTALLOC = api.DISK_STARTALLOC
|
||||
DISK_BACKUP_STARTALLOC = api.DISK_BACKUP_STARTALLOC
|
||||
DISK_BACKUP_ALLOC_FAILED = api.DISK_BACKUP_ALLOC_FAILED
|
||||
DISK_ALLOCATING = api.DISK_ALLOCATING
|
||||
DISK_READY = api.DISK_READY
|
||||
DISK_RESET = api.DISK_RESET // 快照回滚
|
||||
DISK_RESET_FAILED = api.DISK_RESET_FAILED // 快照回滚失败
|
||||
DISK_DEALLOC = api.DISK_DEALLOC
|
||||
DISK_DEALLOC_FAILED = api.DISK_DEALLOC_FAILED
|
||||
DISK_UNKNOWN = api.DISK_UNKNOWN
|
||||
DISK_DETACHING = api.DISK_DETACHING
|
||||
DISK_ATTACHING = api.DISK_ATTACHING
|
||||
DISK_CLONING = api.DISK_CLONING // 硬盘克隆
|
||||
|
||||
DISK_START_SAVE = "start_save"
|
||||
DISK_SAVING = "saving"
|
||||
DISK_START_SAVE = api.DISK_START_SAVE
|
||||
DISK_SAVING = api.DISK_SAVING
|
||||
|
||||
DISK_START_RESIZE = "start_resize"
|
||||
DISK_RESIZING = "resizing"
|
||||
DISK_START_RESIZE = api.DISK_START_RESIZE
|
||||
DISK_RESIZING = api.DISK_RESIZING
|
||||
|
||||
DISK_START_MIGRATE = "start_migrate"
|
||||
DISK_POST_MIGRATE = "post_migrate"
|
||||
DISK_MIGRATING = "migrating"
|
||||
DISK_START_MIGRATE = api.DISK_START_MIGRATE
|
||||
DISK_POST_MIGRATE = api.DISK_POST_MIGRATE
|
||||
DISK_MIGRATING = api.DISK_MIGRATING
|
||||
|
||||
DISK_START_SNAPSHOT = "start_snapshot"
|
||||
DISK_SNAPSHOTING = "snapshoting"
|
||||
DISK_START_SNAPSHOT = api.DISK_START_SNAPSHOT
|
||||
DISK_SNAPSHOTING = api.DISK_SNAPSHOTING
|
||||
|
||||
DISK_TYPE_SYS = "sys"
|
||||
DISK_TYPE_SWAP = "swap"
|
||||
DISK_TYPE_DATA = "data"
|
||||
DISK_TYPE_VOLUME = "volume"
|
||||
DISK_TYPE_SYS = api.DISK_TYPE_SYS
|
||||
DISK_TYPE_SWAP = api.DISK_TYPE_SWAP
|
||||
DISK_TYPE_DATA = api.DISK_TYPE_DATA
|
||||
DISK_TYPE_VOLUME = api.DISK_TYPE_VOLUME
|
||||
|
||||
DISK_BACKING_IMAGE = "image"
|
||||
DISK_BACKING_IMAGE = api.DISK_BACKING_IMAGE
|
||||
)
|
||||
|
||||
type SDiskManager struct {
|
||||
@@ -346,12 +346,11 @@ func (self *SDisk) GetRuningGuestCount() int {
|
||||
}
|
||||
|
||||
func (self *SDisk) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
diskConfig := SDiskConfig{}
|
||||
if err := data.Unmarshal(&diskConfig, "disk"); err != nil {
|
||||
input := new(api.DiskCreateInput)
|
||||
if err := data.Unmarshal(input); err != nil {
|
||||
return err
|
||||
} else {
|
||||
self.fetchDiskInfo(&diskConfig)
|
||||
}
|
||||
self.fetchDiskInfo(input.DiskConfig)
|
||||
return self.SSharableVirtualResourceBase.CustomizeCreate(ctx, userCred, ownerProjId, query, data)
|
||||
}
|
||||
|
||||
@@ -381,17 +380,18 @@ func (self *SDisk) ValidateUpdateData(ctx context.Context, userCred mcclient.Tok
|
||||
}
|
||||
|
||||
func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
disk, err := data.Get("disk")
|
||||
input, err := cmdline.FetchDiskCreateInputByJSON(data)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("disk")
|
||||
return nil, httperrors.NewInputParameterError("parse disk input: %v", err)
|
||||
}
|
||||
|
||||
diskConfig, err := parseDiskInfo(ctx, userCred, disk)
|
||||
diskConfig := input.DiskConfig
|
||||
diskConfig, err = parseDiskInfo(ctx, userCred, diskConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
input.Project = ownerProjId
|
||||
|
||||
storageID := jsonutils.GetAnyString(data, []string{"storage_id", "storage"})
|
||||
storageID := input.Storage
|
||||
if storageID != "" {
|
||||
storageObj, err := StorageManager.FetchByIdOrName(nil, storageID)
|
||||
if err != nil {
|
||||
@@ -406,16 +406,15 @@ func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mc
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.Add(jsonutils.NewString(storage.Id), "storage_id")
|
||||
input.Storage = storage.Id
|
||||
} else {
|
||||
diskConfig.Backend = STORAGE_LOCAL
|
||||
hypervisor, _ := data.GetString("hypervisor")
|
||||
data, err = ValidateScheduleCreateData(ctx, userCred, data, hypervisor)
|
||||
serverInput, err := ValidateScheduleCreateData(ctx, userCred, input.ToServerCreateInput(), input.Hypervisor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
input = serverInput.ToDiskCreateInput()
|
||||
}
|
||||
data.Add(jsonutils.Marshal(diskConfig), "disk")
|
||||
|
||||
if _, err := manager.SSharableVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data); err != nil {
|
||||
return nil, err
|
||||
@@ -424,10 +423,10 @@ func (manager *SDiskManager) ValidateCreateData(ctx context.Context, userCred mc
|
||||
if err := QuotaManager.CheckSetPendingQuota(ctx, userCred, userCred.GetProjectId(), &pendingUsage); err != nil {
|
||||
return nil, httperrors.NewOutOfQuotaError("%s", err)
|
||||
}
|
||||
return data, nil
|
||||
return input.JSON(input), nil
|
||||
}
|
||||
|
||||
func (manager *SDiskManager) validateDiskOnStorage(diskConfig *SDiskConfig, storage *SStorage) error {
|
||||
func (manager *SDiskManager) validateDiskOnStorage(diskConfig *api.DiskConfig, storage *SStorage) error {
|
||||
if !storage.Enabled {
|
||||
return httperrors.NewInputParameterError("Cannot create disk with disabled storage[%s]", storage.Name)
|
||||
}
|
||||
@@ -457,7 +456,27 @@ func (manager *SDiskManager) validateDiskOnStorage(diskConfig *SDiskConfig, stor
|
||||
return nil
|
||||
}
|
||||
|
||||
func (disk *SDisk) SetStorageByHost(hostId string, diskConfig *SDiskConfig) error {
|
||||
func (disk *SDisk) SetStorage(storageId string, diskConfig *api.DiskConfig) error {
|
||||
backend := diskConfig.Backend
|
||||
if backend == "" {
|
||||
return fmt.Errorf("Backend is empty")
|
||||
}
|
||||
storage := StorageManager.FetchStorageById(storageId)
|
||||
if storage == nil {
|
||||
return fmt.Errorf("Not found backend %s storage %s", backend, storageId)
|
||||
}
|
||||
err := DiskManager.validateDiskOnStorage(diskConfig, storage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = db.Update(disk, func() error {
|
||||
disk.StorageId = storage.Id
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (disk *SDisk) SetStorageByHost(hostId string, diskConfig *api.DiskConfig) error {
|
||||
host := HostManager.FetchHostById(hostId)
|
||||
backend := diskConfig.Backend
|
||||
if backend == "" {
|
||||
@@ -497,16 +516,16 @@ func getDiskResourceRequirements(ctx context.Context, userCred mcclient.TokenCre
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *SDiskManager) convertToBatchCreateData(data jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
/*func (manager *SDiskManager) convertToBatchCreateData(data jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
diskConfig, _ := data.Get("disk")
|
||||
newData := data.(*jsonutils.JSONDict).CopyExcludes("disk")
|
||||
newData.Add(diskConfig, "disk.0")
|
||||
return newData
|
||||
}
|
||||
}*/
|
||||
|
||||
func (manager *SDiskManager) OnCreateComplete(ctx context.Context, items []db.IModel, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
pendingUsage := getDiskResourceRequirements(ctx, userCred, data, len(items))
|
||||
RunBatchCreateTask(ctx, items, userCred, manager.convertToBatchCreateData(data), pendingUsage, "DiskBatchCreateTask")
|
||||
RunBatchCreateTask(ctx, items, userCred, data, pendingUsage, "DiskBatchCreateTask")
|
||||
}
|
||||
|
||||
func (self *SDisk) StartDiskCreateTask(ctx context.Context, userCred mcclient.TokenCredential, rebuild bool, snapshot string, parentTaskId string) error {
|
||||
@@ -1144,95 +1163,28 @@ func totalDiskSize(projectId string, active tristate.TriState, ready tristate.Tr
|
||||
return size
|
||||
}
|
||||
|
||||
type SDiskConfig struct {
|
||||
ImageId string `json:"image_id"`
|
||||
|
||||
SnapshotId string `json:"snapshot_id"`
|
||||
DiskType string `json:"disk_type"` // sys, data, swap, volume
|
||||
|
||||
// ImageDiskFormat string
|
||||
SizeMb int `json:"size"` // MB
|
||||
Fs string `json:"fs"` // file system
|
||||
Format string `json:"format"` //
|
||||
Driver string `json:"driver"` //
|
||||
Cache string `json:"cache"` //
|
||||
Mountpoint string `json:"mountpoint"` //
|
||||
Backend string `json:"backend"` // stroageType
|
||||
Medium string `json:"medium"`
|
||||
ImageProperties map[string]string `json:"image_properties"`
|
||||
|
||||
DiskId string `json:"-"` // import only
|
||||
}
|
||||
|
||||
func parseDiskInfo(ctx context.Context, userCred mcclient.TokenCredential, info jsonutils.JSONObject) (*SDiskConfig, error) {
|
||||
diskConfig := SDiskConfig{}
|
||||
|
||||
diskJson, ok := info.(*jsonutils.JSONDict)
|
||||
if ok {
|
||||
err := diskJson.Unmarshal(&diskConfig)
|
||||
if err != nil {
|
||||
func parseDiskInfo(ctx context.Context, userCred mcclient.TokenCredential, info *api.DiskConfig) (*api.DiskConfig, error) {
|
||||
if info.SnapshotId != "" {
|
||||
if err := fillDiskConfigBySnapshot(userCred, info, info.SnapshotId); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &diskConfig, nil
|
||||
}
|
||||
|
||||
// default backend and medium type
|
||||
diskConfig.Backend = "" // STORAGE_LOCAL
|
||||
diskConfig.Medium = DISK_TYPE_HYBRID
|
||||
|
||||
diskStr, err := info.GetString()
|
||||
if err != nil {
|
||||
log.Errorf("invalid diskinfo format %s", err)
|
||||
return nil, err
|
||||
}
|
||||
parts := strings.Split(diskStr, ":")
|
||||
for _, p := range parts {
|
||||
if len(p) == 0 {
|
||||
continue
|
||||
}
|
||||
if regutils.MatchSize(p) {
|
||||
diskConfig.SizeMb, _ = fileutils.GetSizeMb(p, 'M', 1024)
|
||||
} else if utils.IsInStringArray(p, osprofile.FS_TYPES) {
|
||||
diskConfig.Fs = p
|
||||
} else if utils.IsInStringArray(p, osprofile.IMAGE_FORMAT_TYPES) {
|
||||
diskConfig.Format = p
|
||||
} else if utils.IsInStringArray(p, osprofile.DISK_DRIVERS) {
|
||||
diskConfig.Driver = p
|
||||
} else if utils.IsInStringArray(p, osprofile.DISK_CACHE_MODES) {
|
||||
diskConfig.Cache = p
|
||||
} else if utils.IsInStringArray(p, DISK_TYPES) {
|
||||
diskConfig.Medium = p
|
||||
} else if utils.IsInStringArray(p, []string{DISK_TYPE_VOLUME}) {
|
||||
diskConfig.DiskType = p
|
||||
} else if p[0] == '/' {
|
||||
diskConfig.Mountpoint = p
|
||||
} else if p == "autoextend" {
|
||||
diskConfig.SizeMb = -1
|
||||
} else if storageType, exist := StorageManager.IsStorageTypeExist(p); exist {
|
||||
diskConfig.Backend = storageType
|
||||
} else if strings.HasPrefix(p, "snapshot-") {
|
||||
// HACK: use snapshot creat disk format snapshot-id
|
||||
// example: snapshot-3140cecb-ccc4-4865-abae-3a5ba8c69d9b
|
||||
if err := fillDiskConfigBySnapshot(userCred, &diskConfig, p[len("snapshot-"):]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else if len(p) > 0 {
|
||||
if err := fillDiskConfigByImage(ctx, userCred, &diskConfig, p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if info.ImageId != "" {
|
||||
if err := fillDiskConfigByImage(ctx, userCred, info, info.ImageId); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// XXX: do not set default disk size here, set it by each hypervisor driver
|
||||
// if len(diskConfig.ImageId) > 0 && diskConfig.SizeMb == 0 {
|
||||
// diskConfig.SizeMb = options.Options.DefaultDiskSize // MB
|
||||
// else
|
||||
if len(diskConfig.ImageId) == 0 && diskConfig.SizeMb == 0 {
|
||||
if len(info.ImageId) == 0 && info.SizeMb == 0 {
|
||||
return nil, httperrors.NewInputParameterError("Diskinfo not contains either imageID or size")
|
||||
}
|
||||
return &diskConfig, nil
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func fillDiskConfigBySnapshot(userCred mcclient.TokenCredential, diskConfig *SDiskConfig, snapshotId string) error {
|
||||
func fillDiskConfigBySnapshot(userCred mcclient.TokenCredential, diskConfig *api.DiskConfig, snapshotId string) error {
|
||||
iSnapshot, err := SnapshotManager.FetchByIdOrName(userCred, snapshotId)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
@@ -1260,7 +1212,7 @@ func fillDiskConfigBySnapshot(userCred mcclient.TokenCredential, diskConfig *SDi
|
||||
}
|
||||
|
||||
func fillDiskConfigByImage(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
diskConfig *SDiskConfig, imageId string) error {
|
||||
diskConfig *api.DiskConfig, imageId string) error {
|
||||
if userCred == nil {
|
||||
diskConfig.ImageId = imageId
|
||||
} else {
|
||||
@@ -1298,7 +1250,7 @@ func parseIsoInfo(ctx context.Context, userCred mcclient.TokenCredential, imageI
|
||||
return image, nil
|
||||
}
|
||||
|
||||
func (self *SDisk) fetchDiskInfo(diskConfig *SDiskConfig) {
|
||||
func (self *SDisk) fetchDiskInfo(diskConfig *api.DiskConfig) {
|
||||
if len(diskConfig.ImageId) > 0 {
|
||||
self.TemplateId = diskConfig.ImageId
|
||||
self.DiskType = DISK_TYPE_SYS
|
||||
@@ -1343,6 +1295,7 @@ type DiskInfo struct {
|
||||
DiskType string
|
||||
}
|
||||
|
||||
// DEPRECATE: will be remove in future, use ToDiskConfig
|
||||
func (self *SDisk) ToDiskInfo() DiskInfo {
|
||||
ret := DiskInfo{
|
||||
ImageId: self.GetTemplateId(),
|
||||
@@ -1362,6 +1315,26 @@ func (self *SDisk) ToDiskInfo() DiskInfo {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (self *SDisk) ToDiskConfig() *api.DiskConfig {
|
||||
ret := &api.DiskConfig{
|
||||
Index: -1,
|
||||
ImageId: self.GetTemplateId(),
|
||||
Fs: self.GetFsFormat(),
|
||||
Mountpoint: self.GetMountPoint(),
|
||||
Format: self.DiskFormat,
|
||||
SizeMb: self.DiskSize,
|
||||
DiskType: self.DiskType,
|
||||
}
|
||||
storage := self.GetStorage()
|
||||
if storage == nil {
|
||||
return ret
|
||||
}
|
||||
ret.Storage = storage.Id
|
||||
ret.Backend = storage.StorageType
|
||||
ret.Medium = storage.MediumType
|
||||
return ret
|
||||
}
|
||||
|
||||
func (self *SDisk) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
// override
|
||||
log.Infof("disk delete do nothing")
|
||||
|
||||
@@ -109,6 +109,10 @@ func (self *SDynamicschedtag) ValidateUpdateData(ctx context.Context, userCred m
|
||||
return self.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
|
||||
}
|
||||
|
||||
func (self *SDynamicschedtag) GetSchedtag() *SSchedtag {
|
||||
return self.getSchedtag()
|
||||
}
|
||||
|
||||
func (self *SDynamicschedtag) getSchedtag() *SSchedtag {
|
||||
obj, err := SchedtagManager.FetchById(self.SchedtagId)
|
||||
if err != nil {
|
||||
@@ -139,6 +143,10 @@ func (self *SDynamicschedtag) GetExtraDetails(ctx context.Context, userCred mccl
|
||||
return self.getMoreColumns(extra), nil
|
||||
}
|
||||
|
||||
func (manager *SDynamicschedtagManager) GetAllEnabledDynamicSchedtags() []SDynamicschedtag {
|
||||
return manager.getAllEnabledDynamicSchedtags()
|
||||
}
|
||||
|
||||
func (manager *SDynamicschedtagManager) getAllEnabledDynamicSchedtags() []SDynamicschedtag {
|
||||
rules := make([]SDynamicschedtag, 0)
|
||||
|
||||
@@ -185,7 +193,7 @@ func (self *SDynamicschedtag) PerformEvaluate(ctx context.Context, userCred mccl
|
||||
hostDesc := jsonutils.Marshal(host)
|
||||
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(srvDesc, "server")
|
||||
params.Add(srvDesc.JSON(srvDesc), "server")
|
||||
params.Add(hostDesc, "host")
|
||||
|
||||
meet, err := conditionparser.Eval(self.Condition, params)
|
||||
@@ -193,7 +201,7 @@ func (self *SDynamicschedtag) PerformEvaluate(ctx context.Context, userCred mccl
|
||||
return nil, err
|
||||
}
|
||||
result := jsonutils.NewDict()
|
||||
result.Add(srvDesc, "server")
|
||||
result.Add(srvDesc.JSON(srvDesc), "server")
|
||||
result.Add(hostDesc, "host")
|
||||
|
||||
if meet {
|
||||
|
||||
@@ -18,6 +18,9 @@ import (
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/cmdline"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
@@ -703,8 +706,8 @@ func (self *SGuest) StartGueststartTask(ctx context.Context, userCred mcclient.T
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) StartGuestCreateTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, pendingUsage quotas.IQuota, parentTaskId string) error {
|
||||
return self.GetDriver().StartGuestCreateTask(self, ctx, userCred, params, pendingUsage, parentTaskId)
|
||||
func (self *SGuest) StartGuestCreateTask(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput, pendingUsage quotas.IQuota, parentTaskId string) error {
|
||||
return self.GetDriver().StartGuestCreateTask(self, ctx, userCred, input.JSON(input), pendingUsage, parentTaskId)
|
||||
}
|
||||
|
||||
func (self *SGuest) StartSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
@@ -1118,10 +1121,13 @@ 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) {
|
||||
diskSize := 0
|
||||
disksConf := jsonutils.NewDict()
|
||||
disksConf := make([]*api.DiskConfig, 0)
|
||||
diskSizes := make(map[string]int, 0)
|
||||
|
||||
diskDefArray := jsonutils.GetArrayOfPrefix(data, "disk")
|
||||
diskDefArray, err := cmdline.FetchDiskConfigsByJSON(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(diskDefArray) == 0 {
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_CREATE, "No Disk Info Provided", userCred, false)
|
||||
return nil, httperrors.NewBadRequestError("No Disk Info Provided")
|
||||
@@ -1136,7 +1142,7 @@ func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.Tok
|
||||
if len(diskInfo.Backend) == 0 {
|
||||
diskInfo.Backend = self.getDefaultStorageType()
|
||||
}
|
||||
disksConf.Set(fmt.Sprintf("disk.%d", diskIdx), jsonutils.Marshal(diskInfo))
|
||||
disksConf = append(disksConf, diskInfo)
|
||||
if _, ok := diskSizes[diskInfo.Backend]; !ok {
|
||||
diskSizes[diskInfo.Backend] = diskInfo.SizeMb
|
||||
} else {
|
||||
@@ -1163,7 +1169,7 @@ func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.Tok
|
||||
pendingUsage := &SQuota{
|
||||
Storage: diskSize,
|
||||
}
|
||||
err := QuotaManager.CheckSetPendingQuota(ctx, userCred, self.ProjectId, pendingUsage)
|
||||
err = QuotaManager.CheckSetPendingQuota(ctx, userCred, self.ProjectId, pendingUsage)
|
||||
if err != nil {
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_CREATE, err.Error(), userCred, false)
|
||||
return nil, httperrors.NewOutOfQuotaError(err.Error())
|
||||
@@ -1172,7 +1178,7 @@ func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.Tok
|
||||
lockman.LockObject(ctx, host)
|
||||
defer lockman.ReleaseObject(ctx, host)
|
||||
|
||||
err = self.CreateDisksOnHost(ctx, userCred, host, disksConf, pendingUsage, false, false)
|
||||
err = self.CreateDisksOnHost(ctx, userCred, host, disksConf, pendingUsage, false, false, nil)
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, self.ProjectId, nil, pendingUsage)
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_CREATE, err.Error(), userCred, false)
|
||||
@@ -1182,7 +1188,9 @@ func (self *SGuest) PerformCreatedisk(ctx context.Context, userCred mcclient.Tok
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (self *SGuest) StartGuestCreateDiskTask(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, parentTaskId string) error {
|
||||
func (self *SGuest) StartGuestCreateDiskTask(ctx context.Context, userCred mcclient.TokenCredential, disks []*api.DiskConfig, parentTaskId string) error {
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.Marshal(disks), "disks")
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "GuestCreateDiskTask", self, userCred, data, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1394,7 +1402,8 @@ func (self *SGuest) PerformChangeIpaddr(ctx context.Context, userCred mcclient.T
|
||||
log.Errorf("net_desc not found")
|
||||
return nil, httperrors.NewMissingParameterError("net_desc")
|
||||
}
|
||||
conf, err := parseNetworkInfo(userCred, netDesc)
|
||||
conf, err := cmdline.ParseNetworkConfigByJSON(netDesc, -1)
|
||||
conf, err = parseNetworkInfo(userCred, conf)
|
||||
if err != nil {
|
||||
log.Errorf("parseNetworkInfo fail %s", err)
|
||||
return nil, err
|
||||
@@ -1523,7 +1532,12 @@ func (self *SGuest) PerformAttachnetwork(ctx context.Context, userCred mcclient.
|
||||
if err != nil {
|
||||
return nil, httperrors.NewBadRequestError(err.Error())
|
||||
}
|
||||
conf, err := parseNetworkInfo(userCred, netDesc)
|
||||
conf, err := cmdline.ParseNetworkConfigByJSON(netDesc, -1)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewBadRequestError(err.Error())
|
||||
}
|
||||
|
||||
conf, err = parseNetworkInfo(userCred, conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1706,15 +1720,16 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
var diskIdx = 1
|
||||
var newDiskIdx = 0
|
||||
var diskSizes = make(map[string]int, 0)
|
||||
var newDisks = jsonutils.NewDict()
|
||||
var newDisks = make([]*api.DiskConfig, 0)
|
||||
var resizeDisks = jsonutils.NewArray()
|
||||
for {
|
||||
diskNum := fmt.Sprintf("disk.%d", diskIdx)
|
||||
diskDesc, err := data.Get(diskNum)
|
||||
if err != nil || diskDesc == jsonutils.JSONNull {
|
||||
break
|
||||
}
|
||||
diskConf, err := parseDiskInfo(ctx, userCred, diskDesc)
|
||||
|
||||
inputDisks, err := cmdline.FetchDiskConfigsByJSON(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, diskConf := range inputDisks {
|
||||
diskConf, err = parseDiskInfo(ctx, userCred, diskConf)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewBadRequestError("Parse disk info error: %s", err)
|
||||
}
|
||||
@@ -1723,7 +1738,7 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
}
|
||||
if diskConf.SizeMb > 0 {
|
||||
if diskIdx >= len(disks) {
|
||||
newDisks.Add(jsonutils.Marshal(diskConf), fmt.Sprintf("disk.%d", newDiskIdx))
|
||||
newDisks = append(newDisks, diskConf)
|
||||
newDiskIdx += 1
|
||||
addDisk += diskConf.SizeMb
|
||||
storage := host.GetLeastUsedStorage(diskConf.Backend)
|
||||
@@ -1772,8 +1787,8 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
log.Debugf("Skip storage free capacity validating for public cloud: %s", provider.GetId())
|
||||
}
|
||||
|
||||
if newDisks.Length() > 0 {
|
||||
confs.Add(newDisks, "create")
|
||||
if len(newDisks) > 0 {
|
||||
confs.Add(jsonutils.Marshal(newDisks), "create")
|
||||
}
|
||||
if resizeDisks.Length() > 0 {
|
||||
confs.Add(resizeDisks, "resize")
|
||||
@@ -1815,8 +1830,8 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
}
|
||||
}
|
||||
|
||||
if newDisks.Length() > 0 {
|
||||
err := self.CreateDisksOnHost(ctx, userCred, host, newDisks, pendingUsage, false, false)
|
||||
if len(newDisks) > 0 {
|
||||
err := self.CreateDisksOnHost(ctx, userCred, host, newDisks, pendingUsage, false, false, nil)
|
||||
if err != nil {
|
||||
QuotaManager.CancelPendingUsage(ctx, userCred, self.ProjectId, nil, pendingUsage)
|
||||
return nil, httperrors.NewBadRequestError("Create disk on host error: %s", err)
|
||||
@@ -1826,17 +1841,23 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) confToSchedDesc(addCpu, addMem, addDisk int) *jsonutils.JSONDict {
|
||||
desc := jsonutils.NewDict()
|
||||
desc.Set("vmem_size", jsonutils.NewInt(int64(addMem)))
|
||||
desc.Set("vcpu_count", jsonutils.NewInt(int64(addCpu)))
|
||||
func (self *SGuest) confToSchedDesc(addCpu, addMem, addDisk int) *schedapi.ScheduleInput {
|
||||
guestDisks := self.GetDisks()
|
||||
diskInfo := guestDisks[0].ToDiskInfo()
|
||||
diskInfo.Size = int64(addDisk)
|
||||
desc.Set("disk.0", jsonutils.Marshal(diskInfo))
|
||||
desc.Set("prefer_host_id", jsonutils.NewString(self.HostId))
|
||||
desc.Set("hypervisor", jsonutils.NewString(self.GetHypervisor()))
|
||||
desc.Set("owner_tenant_id", jsonutils.NewString(self.ProjectId))
|
||||
diskInfo := guestDisks[0].ToDiskConfig()
|
||||
diskInfo.SizeMb = addDisk
|
||||
|
||||
desc := &schedapi.ScheduleInput{
|
||||
ServerConfig: schedapi.ServerConfig{
|
||||
ServerConfigs: &api.ServerConfigs{
|
||||
Hypervisor: self.Hypervisor,
|
||||
Project: self.ProjectId,
|
||||
PreferHost: self.HostId,
|
||||
Disks: []*api.DiskConfig{diskInfo},
|
||||
},
|
||||
Memory: addMem,
|
||||
Ncpu: addCpu,
|
||||
},
|
||||
}
|
||||
return desc
|
||||
}
|
||||
|
||||
@@ -2700,8 +2721,8 @@ type SImportNic struct {
|
||||
Ifname string `json:"ifname"`
|
||||
}
|
||||
|
||||
func (n SImportNic) ToNetConfig(net *SNetwork) *SNetworkConfig {
|
||||
return &SNetworkConfig{
|
||||
func (n SImportNic) ToNetConfig(net *SNetwork) *api.NetworkConfig {
|
||||
return &api.NetworkConfig{
|
||||
Network: net.Id,
|
||||
Wire: net.WireId,
|
||||
Address: n.Ip,
|
||||
@@ -2725,8 +2746,8 @@ type SImportDisk struct {
|
||||
TemplateId string `json:"template_id"`
|
||||
}
|
||||
|
||||
func (d SImportDisk) ToDiskConfig() *SDiskConfig {
|
||||
ret := &SDiskConfig{
|
||||
func (d SImportDisk) ToDiskConfig() *api.DiskConfig {
|
||||
ret := &api.DiskConfig{
|
||||
SizeMb: d.SizeMb,
|
||||
ImageId: d.TemplateId,
|
||||
Format: d.Format,
|
||||
@@ -2849,7 +2870,7 @@ func (self *SGuest) importDisks(ctx context.Context, userCred mcclient.TokenCred
|
||||
return httperrors.NewInputParameterError("Empty import disks")
|
||||
}
|
||||
for _, disk := range disks {
|
||||
disk, err := self.createDiskOnHost(ctx, userCred, self.GetHost(), disk.ToDiskConfig(), nil, true, true)
|
||||
disk, err := self.createDiskOnHost(ctx, userCred, self.GetHost(), disk.ToDiskConfig(), nil, true, true, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
@@ -247,6 +248,7 @@ func (self *SGuestdisk) Detach(ctx context.Context, userCred mcclient.TokenCrede
|
||||
return db.DetachJoint(ctx, userCred, self)
|
||||
}
|
||||
|
||||
// DEPRECATE: will be remove in future, use ToDiskConfig
|
||||
func (self *SGuestdisk) ToDiskInfo() DiskInfo {
|
||||
disk := self.GetDisk()
|
||||
if disk == nil {
|
||||
@@ -257,3 +259,13 @@ func (self *SGuestdisk) ToDiskInfo() DiskInfo {
|
||||
info.Cache = self.CacheMode
|
||||
return info
|
||||
}
|
||||
|
||||
func (self *SGuestdisk) ToDiskConfig() *api.DiskConfig {
|
||||
disk := self.GetDisk()
|
||||
if disk == nil {
|
||||
return nil
|
||||
}
|
||||
conf := disk.ToDiskConfig()
|
||||
conf.Index = int(self.Index)
|
||||
return conf
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
@@ -30,19 +31,20 @@ type IGuestDriver interface {
|
||||
|
||||
GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest, host *SHost) jsonutils.JSONObject
|
||||
|
||||
ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
|
||||
ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *api.ServerCreateInput) (*api.ServerCreateInput, error)
|
||||
|
||||
ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
|
||||
|
||||
ValidateCreateHostData(ctx context.Context, userCred mcclient.TokenCredential, bmName string, host *SHost, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
|
||||
ValidateCreateHostData(ctx context.Context, userCred mcclient.TokenCredential, bmName string, host *SHost, input *api.ServerCreateInput) (*api.ServerCreateInput, error)
|
||||
|
||||
PrepareDiskRaidConfig(userCred mcclient.TokenCredential, host *SHost, params *jsonutils.JSONDict) error
|
||||
PrepareDiskRaidConfig(userCred mcclient.TokenCredential, host *SHost, params []*api.BaremetalDiskConfig) error
|
||||
|
||||
GetNamedNetworkConfiguration(guest *SGuest, userCred mcclient.TokenCredential, host *SHost, netConfig *SNetworkConfig) (*SNetwork, []SNicConfig, IPAddlocationDirection)
|
||||
GetNamedNetworkConfiguration(guest *SGuest, userCred mcclient.TokenCredential, host *SHost, netConfig *api.NetworkConfig) (*SNetwork, []SNicConfig, IPAddlocationDirection)
|
||||
|
||||
Attach2RandomNetwork(guest *SGuest, ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netConfig *SNetworkConfig, pendingUsage quotas.IQuota) ([]SGuestnetwork, error)
|
||||
Attach2RandomNetwork(guest *SGuest, ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netConfig *api.NetworkConfig, pendingUsage quotas.IQuota) ([]SGuestnetwork, error)
|
||||
GetRandomNetworkTypes() []string
|
||||
|
||||
GetStorageTypes() []string
|
||||
ChooseHostStorage(host *SHost, backend string) *SStorage
|
||||
|
||||
StartGuestCreateTask(guest *SGuest, ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, pendingUsage quotas.IQuota, parentTaskId string) error
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
@@ -629,3 +630,18 @@ func (self *SGuestnetwork) GetShortDesc(ctx context.Context) *jsonutils.JSONDict
|
||||
}
|
||||
return desc
|
||||
}
|
||||
|
||||
func (self *SGuestnetwork) ToNetworkConfig() *api.NetworkConfig {
|
||||
net := self.GetNetwork()
|
||||
if net == nil {
|
||||
return nil
|
||||
}
|
||||
ret := &api.NetworkConfig{
|
||||
Index: int(self.Index),
|
||||
Network: net.Id,
|
||||
Wire: net.GetWire().Id,
|
||||
Address: self.IpAddr,
|
||||
Project: net.ProjectId,
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
+257
-208
@@ -5,7 +5,6 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -13,7 +12,6 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/util/fileutils"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/util/osprofile"
|
||||
"yunion.io/x/pkg/util/regutils"
|
||||
@@ -22,6 +20,9 @@ import (
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/cmdline"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
@@ -349,16 +350,28 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
|
||||
|
||||
secgrpFilter, _ := queryDict.GetString("secgroup")
|
||||
if len(secgrpFilter) > 0 {
|
||||
var notIn = false
|
||||
// HACK FOR NOT IN SECGROUP
|
||||
if strings.HasPrefix(secgrpFilter, "!") {
|
||||
secgrpFilter = secgrpFilter[1:]
|
||||
notIn = true
|
||||
}
|
||||
secgrp, _ := SecurityGroupManager.FetchByIdOrName(nil, secgrpFilter)
|
||||
if secgrp == nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("secgroup %s not found", secgrpFilter)
|
||||
}
|
||||
q = q.Filter(
|
||||
sqlchemy.OR(
|
||||
sqlchemy.In(q.Field("id"), GuestsecgroupManager.Query("guest_id").Equals("secgroup_id", secgrp.GetId()).SubQuery()),
|
||||
sqlchemy.Equals(q.Field("secgrp_id"), secgrp.GetId()),
|
||||
),
|
||||
)
|
||||
|
||||
if notIn {
|
||||
filter1 := sqlchemy.NotIn(q.Field("id"),
|
||||
GuestsecgroupManager.Query("guest_id").Equals("secgroup_id", secgrp.GetId()).SubQuery())
|
||||
filter2 := sqlchemy.NotEquals(q.Field("secgrp_id"), secgrp.GetId())
|
||||
q = q.Filter(sqlchemy.AND(filter1, filter2))
|
||||
} else {
|
||||
filter1 := sqlchemy.In(q.Field("id"),
|
||||
GuestsecgroupManager.Query("guest_id").Equals("secgroup_id", secgrp.GetId()).SubQuery())
|
||||
filter2 := sqlchemy.Equals(q.Field("secgrp_id"), secgrp.GetId())
|
||||
q = q.Filter(sqlchemy.OR(filter1, filter2))
|
||||
}
|
||||
}
|
||||
|
||||
zoneFilter, _ := queryDict.GetString("zone")
|
||||
@@ -400,6 +413,23 @@ func (manager *SGuestManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQ
|
||||
q = q.In("host_id", sq)
|
||||
}
|
||||
|
||||
vpcFilter, err := queryDict.GetString("vpc")
|
||||
if err == nil {
|
||||
IVpc, err := VpcManager.FetchByIdOrName(userCred, vpcFilter)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("Vpc %s not found", vpcFilter)
|
||||
}
|
||||
vpc := IVpc.(*SVpc)
|
||||
guestnetwork := GuestnetworkManager.Query().SubQuery()
|
||||
network := NetworkManager.Query().SubQuery()
|
||||
wire := WireManager.Query().SubQuery()
|
||||
sq := guestnetwork.Query(guestnetwork.Field("guest_id")).Join(network,
|
||||
sqlchemy.Equals(guestnetwork.Field("network_id"), network.Field("id"))).
|
||||
Join(wire, sqlchemy.Equals(network.Field("wire_id"), wire.Field("id"))).
|
||||
Filter(sqlchemy.Equals(wire.Field("vpc_id"), vpc.Id)).SubQuery()
|
||||
q = q.In("id", sq)
|
||||
}
|
||||
|
||||
diskFilter, _ := queryDict.GetString("disk")
|
||||
if len(diskFilter) > 0 {
|
||||
diskI, _ := DiskManager.FetchByIdOrName(userCred, diskFilter)
|
||||
@@ -722,47 +752,30 @@ func (guest *SGuest) ValidateResizeDisk(disk *SDisk, storage *SStorage) error {
|
||||
return guest.GetDriver().ValidateResizeDisk(guest, disk, storage)
|
||||
}
|
||||
|
||||
func ValidateMemCpuData(data jsonutils.JSONObject) (int, int, error) {
|
||||
vmemSize := 0
|
||||
vcpuCount := 0
|
||||
var err error
|
||||
|
||||
hypervisor, _ := data.GetString("hypervisor")
|
||||
func ValidateMemCpuData(vmemSize, vcpuCount int, hypervisor string) (int, int, error) {
|
||||
if len(hypervisor) == 0 {
|
||||
hypervisor = HYPERVISOR_DEFAULT
|
||||
}
|
||||
driver := GetDriver(hypervisor)
|
||||
|
||||
vmemStr, _ := data.GetString("vmem_size")
|
||||
if len(vmemStr) > 0 {
|
||||
if !regutils.MatchSize(vmemStr) {
|
||||
return 0, 0, httperrors.NewInputParameterError("Memory size must be number[+unit], like 256M, 1G or 256")
|
||||
}
|
||||
vmemSize, err = fileutils.GetSizeMb(vmemStr, 'M', 1024)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
if vmemSize > 0 {
|
||||
maxVmemGb := driver.GetMaxVMemSizeGB()
|
||||
if vmemSize < 8 || vmemSize > maxVmemGb*1024 {
|
||||
return 0, 0, httperrors.NewInputParameterError("Memory size must be 8MB ~ %d GB", maxVmemGb)
|
||||
}
|
||||
}
|
||||
vcpuStr, _ := data.GetString("vcpu_count")
|
||||
if len(vcpuStr) > 0 {
|
||||
if !regutils.MatchInteger(vcpuStr) {
|
||||
return 0, 0, httperrors.NewInputParameterError("CPU core count must be integer")
|
||||
}
|
||||
vcpuCount, _ = strconv.Atoi(vcpuStr)
|
||||
maxVcpuCount := driver.GetMaxVCpuCount()
|
||||
if vcpuCount < 1 || vcpuCount > maxVcpuCount {
|
||||
return 0, 0, httperrors.NewInputParameterError("CPU core count must be 1 ~ %d", maxVcpuCount)
|
||||
}
|
||||
|
||||
maxVcpuCount := driver.GetMaxVCpuCount()
|
||||
if vcpuCount < 1 || vcpuCount > maxVcpuCount {
|
||||
return 0, 0, httperrors.NewInputParameterError("CPU core count must be 1 ~ %d", maxVcpuCount)
|
||||
}
|
||||
return vmemSize, vcpuCount, 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)
|
||||
memSize, _ := data.Int("vmem_size")
|
||||
cpuCount, _ := data.Int("vcpu_count")
|
||||
vmemSize, vcpuCount, err := ValidateMemCpuData(int(memSize), int(cpuCount), self.Hypervisor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -802,26 +815,33 @@ func (self *SGuest) ValidateUpdateData(ctx context.Context, userCred mcclient.To
|
||||
}
|
||||
|
||||
func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
resetPassword := jsonutils.QueryBoolean(data, "reset_password", true)
|
||||
passwd, _ := data.GetString("password")
|
||||
// TODO: 定义 api.ServerCreateInput 的 Unmarshal 函数,直接通过 data.Unmarshal(input) 解析参数
|
||||
input, err := cmdline.FetchServerCreateInputByJSON(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resetPassword := true
|
||||
if input.ResetPassword != nil {
|
||||
resetPassword = *input.ResetPassword
|
||||
}
|
||||
|
||||
passwd := input.Password
|
||||
if resetPassword && len(passwd) > 0 {
|
||||
if !seclib2.MeetComplxity(passwd) {
|
||||
return nil, httperrors.NewWeakPasswordError()
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
var hypervisor string
|
||||
// var rootStorageType string
|
||||
var osProf osprofile.SOSProfile
|
||||
hypervisor, _ = data.GetString("hypervisor")
|
||||
hypervisor = input.Hypervisor
|
||||
if hypervisor != HYPERVISOR_CONTAINER {
|
||||
|
||||
disk0Json, _ := data.Get("disk.0")
|
||||
if disk0Json == nil || disk0Json == jsonutils.JSONNull {
|
||||
if len(input.Disks) == 0 {
|
||||
return nil, httperrors.NewInputParameterError("No disk information provided")
|
||||
}
|
||||
diskConfig, err := parseDiskInfo(ctx, userCred, disk0Json)
|
||||
diskConfig := input.Disks[0]
|
||||
diskConfig, err = parseDiskInfo(ctx, userCred, diskConfig)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("Invalid root image: %s", err)
|
||||
}
|
||||
@@ -838,19 +858,16 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
// }
|
||||
// rootStorageType = diskConfig.Backend
|
||||
|
||||
data.Add(jsonutils.Marshal(diskConfig), "disk.0")
|
||||
input.Disks[0] = diskConfig
|
||||
|
||||
imgProperties := diskConfig.ImageProperties
|
||||
if data.Contains("cdrom") {
|
||||
cdromStr, err := data.GetString("cdrom")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid cdrom device description %s", err)
|
||||
}
|
||||
if input.Cdrom != "" {
|
||||
cdromStr := input.Cdrom
|
||||
image, err := parseIsoInfo(ctx, userCred, cdromStr)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("parse cdrom device info error %s", err)
|
||||
}
|
||||
data.Add(jsonutils.NewString(image.Id), "cdrom")
|
||||
input.Cdrom = image.Id
|
||||
if len(imgProperties) == 0 {
|
||||
imgProperties = image.Properties
|
||||
}
|
||||
@@ -860,7 +877,7 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
imgProperties = map[string]string{"os_type": "Linux"}
|
||||
}
|
||||
|
||||
osType, _ := data.GetString("os_type")
|
||||
osType := input.OsType
|
||||
osProf, err = osprofile.GetOSProfileFromImageProperties(imgProperties, hypervisor)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("Invalid root image: %s", err)
|
||||
@@ -868,36 +885,36 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
|
||||
if len(osProf.Hypervisor) > 0 && len(hypervisor) == 0 {
|
||||
hypervisor = osProf.Hypervisor
|
||||
data.Add(jsonutils.NewString(osProf.Hypervisor), "hypervisor")
|
||||
input.Hypervisor = hypervisor
|
||||
}
|
||||
if len(osProf.OSType) > 0 && len(osType) == 0 {
|
||||
osType = osProf.OSType
|
||||
data.Add(jsonutils.NewString(osProf.OSType), "os_type")
|
||||
input.OsType = osType
|
||||
}
|
||||
data.Add(jsonutils.Marshal(osProf), "__os_profile__")
|
||||
input.OsProfile = jsonutils.Marshal(osProf)
|
||||
}
|
||||
|
||||
data, err = ValidateScheduleCreateData(ctx, userCred, data, hypervisor)
|
||||
input, err = ValidateScheduleCreateData(ctx, userCred, input, hypervisor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
hypervisor, _ = data.GetString("hypervisor")
|
||||
hypervisor = input.Hypervisor
|
||||
if hypervisor != HYPERVISOR_CONTAINER {
|
||||
// support sku here
|
||||
var sku *SServerSku
|
||||
skuName := jsonutils.GetAnyString(data, []string{"sku", "flavor", "instance_type"})
|
||||
skuName := input.InstanceType
|
||||
if len(skuName) > 0 {
|
||||
sku, err := ServerSkuManager.FetchSkuByNameAndHypervisor(skuName, hypervisor, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data.Add(jsonutils.NewString(sku.Name), "instance_type")
|
||||
data.Add(jsonutils.NewInt(int64(sku.MemorySizeMB)), "vmem_size")
|
||||
data.Add(jsonutils.NewInt(int64(sku.CpuCoreCount)), "vcpu_count")
|
||||
input.InstanceType = sku.Name
|
||||
input.VmemSize = sku.MemorySizeMB
|
||||
input.VcpuCount = sku.CpuCoreCount
|
||||
} else {
|
||||
vmemSize, vcpuCount, err := ValidateMemCpuData(data)
|
||||
vmemSize, vcpuCount, err := ValidateMemCpuData(input.VmemSize, input.VcpuCount, input.Hypervisor)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -908,28 +925,28 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
if vcpuCount == 0 {
|
||||
vcpuCount = 1
|
||||
}
|
||||
data.Add(jsonutils.NewInt(int64(vmemSize)), "vmem_size")
|
||||
data.Add(jsonutils.NewInt(int64(vcpuCount)), "vcpu_count")
|
||||
input.VmemSize = vmemSize
|
||||
input.VcpuCount = vcpuCount
|
||||
}
|
||||
|
||||
dataDiskDefs := make([]string, 0)
|
||||
dataDiskDefs := []*api.DiskConfig{}
|
||||
if sku != nil && sku.AttachedDiskCount > 0 {
|
||||
for i := 0; i < sku.AttachedDiskCount; i += 1 {
|
||||
dataDiskDefs = append(dataDiskDefs, fmt.Sprintf("%dg:%s", sku.AttachedDiskSizeGB, sku.AttachedDiskType))
|
||||
dataDisk := &api.DiskConfig{
|
||||
SizeMb: sku.AttachedDiskSizeGB * 1024,
|
||||
Backend: strings.ToLower(sku.AttachedDiskType),
|
||||
}
|
||||
dataDiskDefs = append(dataDiskDefs, dataDisk)
|
||||
}
|
||||
}
|
||||
|
||||
// start from data disk
|
||||
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)
|
||||
}
|
||||
dataDiskDefs = append(dataDiskDefs, diskJson)
|
||||
disks := input.Disks
|
||||
for idx := 1; idx < len(disks); idx += 1 {
|
||||
dataDiskDefs = append(dataDiskDefs, disks[idx])
|
||||
}
|
||||
|
||||
rootDiskConfig, err := parseDiskInfo(ctx, userCred, jsonArray[0])
|
||||
rootDiskConfig, err := parseDiskInfo(ctx, userCred, disks[0])
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err) // should no error
|
||||
}
|
||||
@@ -940,10 +957,11 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
rootDiskConfig.SizeMb = GetDriver(hypervisor).GetMinimalSysDiskSizeGb() * 1024
|
||||
}
|
||||
log.Debugf("ROOT DISK: %#v", rootDiskConfig)
|
||||
data.Set("disk.0", jsonutils.Marshal(rootDiskConfig))
|
||||
input.Disks[0] = rootDiskConfig
|
||||
//data.Set("disk.0", jsonutils.Marshal(rootDiskConfig))
|
||||
|
||||
for i := 0; i < len(dataDiskDefs); i += 1 {
|
||||
diskConfig, err := parseDiskInfo(ctx, userCred, jsonutils.NewString(dataDiskDefs[i]))
|
||||
diskConfig, err := parseDiskInfo(ctx, userCred, dataDiskDefs[i])
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("parse disk description error %s", err)
|
||||
}
|
||||
@@ -956,11 +974,11 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
if len(diskConfig.Driver) == 0 {
|
||||
diskConfig.Driver = osProf.DiskDriver
|
||||
}
|
||||
data.Set(fmt.Sprintf("disk.%d", i+1), jsonutils.Marshal(diskConfig))
|
||||
input.Disks[i+1] = diskConfig
|
||||
}
|
||||
|
||||
resourceTypeStr := jsonutils.GetAnyString(data, []string{"resource_type"})
|
||||
durationStr := jsonutils.GetAnyString(data, []string{"duration"})
|
||||
resourceTypeStr := input.ResourceType
|
||||
durationStr := input.Duration
|
||||
|
||||
if len(durationStr) > 0 {
|
||||
|
||||
@@ -981,18 +999,18 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
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")
|
||||
input.BillingType = BILLING_TYPE_PREPAID
|
||||
input.BillingCycle = billingCycle.String()
|
||||
// expired_at will be set later by callback
|
||||
// data.Add(jsonutils.NewTimeString(billingCycle.EndAt(time.Time{})), "expired_at")
|
||||
|
||||
data.Set("duration", jsonutils.NewString(billingCycle.String()))
|
||||
input.Duration = billingCycle.String()
|
||||
}
|
||||
}
|
||||
|
||||
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])
|
||||
netArray := input.Networks
|
||||
for idx := 0; idx < len(netArray); idx += 1 {
|
||||
netConfig, err := parseNetworkInfo(userCred, netArray[idx])
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("parse network description error %s", err)
|
||||
}
|
||||
@@ -1003,12 +1021,12 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
if len(netConfig.Driver) == 0 {
|
||||
netConfig.Driver = osProf.NetDriver
|
||||
}
|
||||
data.Set(fmt.Sprintf("net.%d", idx), jsonutils.Marshal(netConfig))
|
||||
input.Networks[idx] = netConfig
|
||||
}
|
||||
|
||||
isoDevArray := jsonutils.GetArrayOfPrefix(data, "isolated_device")
|
||||
isoDevArray := input.IsolatedDevices
|
||||
for idx := 0; idx < len(isoDevArray); idx += 1 { // .Contains(fmt.Sprintf("isolated_device.%d", idx)); idx += 1 {
|
||||
if jsonutils.QueryBoolean(data, "backup", false) {
|
||||
if input.Backup {
|
||||
return nil, httperrors.NewBadRequestError("Cannot create backup with isolated device")
|
||||
}
|
||||
devConfig, err := IsolatedDeviceManager.parseDeviceInfo(userCred, isoDevArray[idx])
|
||||
@@ -1019,36 +1037,33 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.Set(fmt.Sprintf("isolated_device.%d", idx), jsonutils.Marshal(devConfig))
|
||||
input.IsolatedDevices[idx] = devConfig
|
||||
}
|
||||
|
||||
keypairId, _ := data.GetString("keypair")
|
||||
if len(keypairId) == 0 {
|
||||
keypairId, _ = data.GetString("keypair_id")
|
||||
}
|
||||
keypairId := input.Keypair
|
||||
if len(keypairId) > 0 {
|
||||
keypairObj, err := KeypairManager.FetchByIdOrName(userCred, keypairId)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("Keypair %s not found", keypairId)
|
||||
}
|
||||
data.Add(jsonutils.NewString(keypairObj.GetId()), "keypair_id")
|
||||
input.Keypair = keypairObj.GetId()
|
||||
} else {
|
||||
data.Add(jsonutils.NewString("None"), "keypair_id")
|
||||
input.Keypair = "None" // TODO: ??? None?
|
||||
}
|
||||
|
||||
if data.Contains("secgroup") {
|
||||
secGrpId, _ := data.GetString("secgroup")
|
||||
if input.Secgroup != "" {
|
||||
secGrpId := input.Secgroup
|
||||
secGrpObj, err := SecurityGroupManager.FetchByIdOrName(userCred, secGrpId)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("Secgroup %s not found", secGrpId)
|
||||
}
|
||||
data.Add(jsonutils.NewString(secGrpObj.GetId()), "secgrp_id")
|
||||
input.Secgroup = secGrpObj.GetId()
|
||||
} else {
|
||||
data.Add(jsonutils.NewString("default"), "secgrp_id")
|
||||
input.Secgroup = "default"
|
||||
}
|
||||
|
||||
eipStr, _ := data.GetString("eip")
|
||||
eipBw, _ := data.Int("eip_bw")
|
||||
eipStr := input.Eip
|
||||
eipBw := input.EipBw
|
||||
if len(eipStr) > 0 || eipBw > 0 {
|
||||
if !GetDriver(hypervisor).IsSupportEip() {
|
||||
return nil, httperrors.NewNotImplementedError("eip not supported for %s", hypervisor)
|
||||
@@ -1070,14 +1085,14 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
if eip.IsAssociated() {
|
||||
return nil, httperrors.NewResourceBusyError("eip %s has been associated", eipStr)
|
||||
}
|
||||
data.Set("eip_id", jsonutils.NewString(eipObj.GetId()))
|
||||
input.Eip = eipObj.GetId()
|
||||
|
||||
eipRegion := eip.GetRegion()
|
||||
preferRegionId, _ := data.GetString("prefer_region_id")
|
||||
if len(preferRegionId) > 0 && preferRegionId != eipRegion.Id {
|
||||
return nil, httperrors.NewConflictError("cannot assoicate with eip %s: different region", eipStr)
|
||||
}
|
||||
data.Set("prefer_region_id", jsonutils.NewString(eipRegion.Id))
|
||||
input.PreferRegion = eipRegion.Id
|
||||
} else {
|
||||
// create new eip
|
||||
}
|
||||
@@ -1090,30 +1105,33 @@ func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred m
|
||||
|
||||
}*/
|
||||
|
||||
data, err = GetDriver(hypervisor).ValidateCreateData(ctx, userCred, data)
|
||||
input, err = GetDriver(hypervisor).ValidateCreateData(ctx, userCred, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, data)
|
||||
data, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerProjId, query, input.JSON(input))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := data.Unmarshal(input); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !jsonutils.QueryBoolean(data, "is_system", false) {
|
||||
err = manager.checkCreateQuota(ctx, userCred, ownerProjId, data,
|
||||
jsonutils.QueryBoolean(data, "backup", false))
|
||||
if !input.IsSystem {
|
||||
err = manager.checkCreateQuota(ctx, userCred, ownerProjId, input,
|
||||
input.Backup)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
data.Add(jsonutils.NewString(ownerProjId), "owner_tenant_id")
|
||||
return data, nil
|
||||
input.Project = ownerProjId
|
||||
return input.JSON(input), nil
|
||||
}
|
||||
|
||||
func (manager *SGuestManager) checkCreateQuota(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, data *jsonutils.JSONDict, hasBackup bool) error {
|
||||
req := getGuestResourceRequirements(ctx, userCred, data, 1, hasBackup)
|
||||
func (manager *SGuestManager) checkCreateQuota(ctx context.Context, userCred mcclient.TokenCredential, ownerProjId string, input *api.ServerCreateInput, hasBackup bool) error {
|
||||
req := getGuestResourceRequirements(ctx, userCred, input, 1, hasBackup)
|
||||
err := QuotaManager.CheckSetPendingQuota(ctx, userCred, ownerProjId, &req)
|
||||
if err != nil {
|
||||
return httperrors.NewOutOfQuotaError(err.Error())
|
||||
@@ -1138,35 +1156,27 @@ func (self *SGuest) checkUpdateQuota(ctx context.Context, userCred mcclient.Toke
|
||||
return err
|
||||
}
|
||||
|
||||
func getGuestResourceRequirements(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject, count int, hasBackup bool) SQuota {
|
||||
vcpuCount, _ := data.Int("vcpu_count")
|
||||
func getGuestResourceRequirements(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput, count int, hasBackup bool) SQuota {
|
||||
vcpuCount := input.VcpuCount
|
||||
if vcpuCount == 0 {
|
||||
vcpuCount = 1
|
||||
}
|
||||
|
||||
vmemSize, _ := data.Int("vmem_size")
|
||||
vmemSize := input.VmemSize
|
||||
|
||||
diskSize := 0
|
||||
|
||||
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])
|
||||
for _, diskConfig := range input.Disks {
|
||||
diskSize += diskConfig.SizeMb
|
||||
}
|
||||
|
||||
isoDevArray := jsonutils.GetArrayOfPrefix(data, "isolated_device")
|
||||
devCount := len(isoDevArray)
|
||||
// for idx := 0; data.Contains(fmt.Sprintf("isolated_device.%d", idx)); idx += 1 {
|
||||
// devCount += 1
|
||||
//}
|
||||
devCount := len(input.IsolatedDevices)
|
||||
|
||||
eNicCnt := 0
|
||||
iNicCnt := 0
|
||||
eBw := 0
|
||||
iBw := 0
|
||||
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])
|
||||
for _, netConfig := range input.Networks {
|
||||
if isExitNetworkInfo(netConfig) {
|
||||
eNicCnt += 1
|
||||
eBw += netConfig.BwLimit
|
||||
@@ -1182,7 +1192,7 @@ func getGuestResourceRequirements(ctx context.Context, userCred mcclient.TokenCr
|
||||
}
|
||||
|
||||
eipCnt := 0
|
||||
eipBw, _ := data.Int("eip_bw")
|
||||
eipBw := input.EipBw
|
||||
if eipBw > 0 {
|
||||
eipCnt = 1
|
||||
}
|
||||
@@ -1238,8 +1248,9 @@ func (guest *SGuest) setApptags(ctx context.Context, appTags []string, userCred
|
||||
}
|
||||
|
||||
func (manager *SGuestManager) OnCreateComplete(ctx context.Context, items []db.IModel, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
pendingUsage := getGuestResourceRequirements(ctx, userCred, data, len(items),
|
||||
jsonutils.QueryBoolean(data, "backup", false))
|
||||
input := new(api.ServerCreateInput)
|
||||
data.Unmarshal(input)
|
||||
pendingUsage := getGuestResourceRequirements(ctx, userCred, input, len(items), input.Backup)
|
||||
RunBatchCreateTask(ctx, items, userCred, data, pendingUsage, "GuestBatchCreateTask")
|
||||
}
|
||||
|
||||
@@ -1371,6 +1382,17 @@ func (self *SGuest) moreExtraInfo(extra *jsonutils.JSONDict) *jsonutils.JSONDict
|
||||
extra.Add(jsonutils.JSONTrue, "can_recycle")
|
||||
}
|
||||
|
||||
guestnetworks, _ := self.GetNetworks("")
|
||||
if len(guestnetworks) > 0 {
|
||||
guestnetwork := guestnetworks[0]
|
||||
network := guestnetwork.GetNetwork()
|
||||
if network != nil {
|
||||
vpc := network.GetVpc()
|
||||
extra.Set("vpc_id", jsonutils.NewString(vpc.Id))
|
||||
extra.Set("vpc", jsonutils.NewString(vpc.Name))
|
||||
}
|
||||
}
|
||||
|
||||
return extra
|
||||
}
|
||||
|
||||
@@ -1831,6 +1853,18 @@ func (self *SGuest) syncRemoveCloudVM(ctx context.Context, userCred mcclient.Tok
|
||||
lockman.LockObject(ctx, self)
|
||||
defer lockman.ReleaseObject(ctx, self)
|
||||
|
||||
if self.BillingType == BILLING_TYPE_PREPAID {
|
||||
diff, err := db.Update(self, func() error {
|
||||
self.BillingType = BILLING_TYPE_POSTPAID
|
||||
self.ExpiredAt = time.Time{}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
db.OpsLog.LogSyncUpdate(self, diff, userCred)
|
||||
}
|
||||
|
||||
return self.SetStatus(userCred, VM_UNKNOWN, "Sync lost")
|
||||
}
|
||||
|
||||
@@ -2520,23 +2554,22 @@ func totalGuestResourceCount(
|
||||
return stat
|
||||
}
|
||||
|
||||
func (self *SGuest) getDefaultNetworkConfig() *SNetworkConfig {
|
||||
netConf := SNetworkConfig{}
|
||||
func (self *SGuest) getDefaultNetworkConfig() *api.NetworkConfig {
|
||||
netConf := api.NetworkConfig{}
|
||||
netConf.BwLimit = options.Options.DefaultBandwidth
|
||||
osProf := self.getOSProfile()
|
||||
netConf.Driver = osProf.NetDriver
|
||||
return &netConf
|
||||
}
|
||||
|
||||
func (self *SGuest) CreateNetworksOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, data *jsonutils.JSONDict, pendingUsage quotas.IQuota) error {
|
||||
netJsonArray := jsonutils.GetArrayOfPrefix(data, "net")
|
||||
if len(netJsonArray) == 0 {
|
||||
func (self *SGuest) CreateNetworksOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netArray []*api.NetworkConfig, pendingUsage quotas.IQuota) error {
|
||||
if len(netArray) == 0 {
|
||||
netConfig := self.getDefaultNetworkConfig()
|
||||
_, err := self.attach2RandomNetwork(ctx, userCred, host, netConfig, pendingUsage)
|
||||
return err
|
||||
}
|
||||
for idx := 0; idx < len(netJsonArray); idx += 1 {
|
||||
netConfig, err := parseNetworkInfo(userCred, netJsonArray[idx])
|
||||
for _, netConfig := range netArray {
|
||||
netConfig, err := parseNetworkInfo(userCred, netConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -2548,7 +2581,7 @@ func (self *SGuest) CreateNetworksOnHost(ctx context.Context, userCred mcclient.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) attach2NetworkDesc(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netConfig *SNetworkConfig, pendingUsage quotas.IQuota) ([]SGuestnetwork, error) {
|
||||
func (self *SGuest) attach2NetworkDesc(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netConfig *api.NetworkConfig, pendingUsage quotas.IQuota) ([]SGuestnetwork, error) {
|
||||
var gns []SGuestnetwork
|
||||
var err1, err2 error
|
||||
if len(netConfig.Network) > 0 {
|
||||
@@ -2568,7 +2601,7 @@ func (self *SGuest) attach2NetworkDesc(ctx context.Context, userCred mcclient.To
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuest) attach2NamedNetworkDesc(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netConfig *SNetworkConfig, pendingUsage quotas.IQuota) ([]SGuestnetwork, error) {
|
||||
func (self *SGuest) attach2NamedNetworkDesc(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netConfig *api.NetworkConfig, pendingUsage quotas.IQuota) ([]SGuestnetwork, error) {
|
||||
driver := self.GetDriver()
|
||||
net, nicConfs, allocDir := driver.GetNamedNetworkConfiguration(self, userCred, host, netConfig)
|
||||
if net != nil {
|
||||
@@ -2587,33 +2620,38 @@ func (self *SGuest) attach2NamedNetworkDesc(ctx context.Context, userCred mcclie
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuest) attach2RandomNetwork(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netConfig *SNetworkConfig, pendingUsage quotas.IQuota) ([]SGuestnetwork, error) {
|
||||
func (self *SGuest) attach2RandomNetwork(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netConfig *api.NetworkConfig, pendingUsage quotas.IQuota) ([]SGuestnetwork, error) {
|
||||
driver := self.GetDriver()
|
||||
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, inheritBilling bool, isWithServerCreate 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])
|
||||
func (self *SGuest) CreateDisksOnHost(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
host *SHost,
|
||||
disks []*api.DiskConfig,
|
||||
pendingUsage quotas.IQuota,
|
||||
inheritBilling bool,
|
||||
isWithServerCreate bool,
|
||||
candidate *schedapi.CandidateResource,
|
||||
) error {
|
||||
for idx := 0; idx < len(disks); idx += 1 {
|
||||
diskConfig, err := parseDiskInfo(ctx, userCred, disks[idx])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
disk, err := self.createDiskOnHost(ctx, userCred, host, diskConfig, pendingUsage, inheritBilling, isWithServerCreate)
|
||||
disk, err := self.createDiskOnHost(ctx, userCred, host, diskConfig, pendingUsage, inheritBilling, isWithServerCreate, candidate.Disks[idx])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data.Add(jsonutils.NewString(disk.Id), fmt.Sprintf("disk.%d.id", idx))
|
||||
if len(diskConfig.SnapshotId) > 0 {
|
||||
data.Add(jsonutils.NewString(diskConfig.SnapshotId), fmt.Sprintf("disk.%d.snapshot", idx))
|
||||
}
|
||||
diskConfig.DiskId = disk.Id
|
||||
disks[idx] = diskConfig
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) createDiskOnStorage(ctx context.Context, userCred mcclient.TokenCredential, storage *SStorage,
|
||||
diskConfig *SDiskConfig, pendingUsage quotas.IQuota, inheritBilling bool, isWithServerCreate bool) (*SDisk, error) {
|
||||
diskConfig *api.DiskConfig, pendingUsage quotas.IQuota, inheritBilling bool, isWithServerCreate bool) (*SDisk, error) {
|
||||
lockman.LockObject(ctx, storage)
|
||||
defer lockman.ReleaseObject(ctx, storage)
|
||||
|
||||
@@ -2647,9 +2685,26 @@ 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, inheritBilling bool, isWithServerCreate bool) (*SDisk, error) {
|
||||
storage := self.GetDriver().ChooseHostStorage(host, diskConfig.Backend)
|
||||
func (self *SGuest) ChooseHostStorage(host *SHost, backend string, candidate *schedapi.CandidateDisk) *SStorage {
|
||||
log.Errorf("==========candidate %#v", candidate)
|
||||
if candidate == nil {
|
||||
return self.GetDriver().ChooseHostStorage(host, backend)
|
||||
}
|
||||
return StorageManager.FetchStorageById(candidate.StorageId)
|
||||
}
|
||||
|
||||
func (self *SGuest) createDiskOnHost(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
host *SHost,
|
||||
diskConfig *api.DiskConfig,
|
||||
pendingUsage quotas.IQuota,
|
||||
inheritBilling bool,
|
||||
isWithServerCreate bool,
|
||||
candidate *schedapi.CandidateDisk,
|
||||
) (*SDisk, error) {
|
||||
storage := self.ChooseHostStorage(host, diskConfig.Backend, candidate)
|
||||
log.Debugf("Choose storage %s:%s for disk %#v", storage.Name, storage.Id, diskConfig)
|
||||
if storage == nil {
|
||||
return nil, fmt.Errorf("No storage on %s to create disk for %s", host.GetName(), diskConfig.Backend)
|
||||
}
|
||||
@@ -2657,6 +2712,7 @@ func (self *SGuest) createDiskOnHost(ctx context.Context, userCred mcclient.Toke
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: use scheduler candidate storage
|
||||
if len(self.BackupHostId) > 0 {
|
||||
backupHost := HostManager.FetchHostById(self.BackupHostId)
|
||||
backupStorage := self.GetDriver().ChooseHostStorage(backupHost, diskConfig.Backend)
|
||||
@@ -2674,14 +2730,10 @@ func (self *SGuest) createDiskOnHost(ctx context.Context, userCred mcclient.Toke
|
||||
return disk, err
|
||||
}
|
||||
|
||||
func (self *SGuest) CreateIsolatedDeviceOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, data *jsonutils.JSONDict, pendingUsage quotas.IQuota) error {
|
||||
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
|
||||
}
|
||||
err = self.createIsolatedDeviceOnHost(ctx, userCred, host, devConfig, pendingUsage)
|
||||
func (self *SGuest) CreateIsolatedDeviceOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, devs []*api.IsolatedDeviceConfig, pendingUsage quotas.IQuota) error {
|
||||
for idx := 0; idx < len(devs); idx += 1 {
|
||||
devConfig := devs[idx]
|
||||
err := self.createIsolatedDeviceOnHost(ctx, userCred, host, devConfig, pendingUsage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -2689,7 +2741,7 @@ func (self *SGuest) CreateIsolatedDeviceOnHost(ctx context.Context, userCred mcc
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) createIsolatedDeviceOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, devConfig *SIsolatedDeviceConfig, pendingUsage quotas.IQuota) error {
|
||||
func (self *SGuest) createIsolatedDeviceOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, devConfig *api.IsolatedDeviceConfig, pendingUsage quotas.IQuota) error {
|
||||
lockman.LockClass(ctx, QuotaManager, self.ProjectId)
|
||||
defer lockman.ReleaseClass(ctx, QuotaManager, self.ProjectId)
|
||||
|
||||
@@ -2871,24 +2923,15 @@ func (self *SGuest) DeleteAllDisksInDB(ctx context.Context, userCred mcclient.To
|
||||
return nil
|
||||
}
|
||||
|
||||
type SDeployConfig struct {
|
||||
Path string
|
||||
Action string
|
||||
Content string
|
||||
}
|
||||
|
||||
func (self *SGuest) GetDeployConfigOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, params *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
config := jsonutils.NewDict()
|
||||
|
||||
desc := self.GetDriver().GetJsonDescAtHost(ctx, userCred, self, host)
|
||||
config.Add(desc, "desc")
|
||||
|
||||
deploys := make([]SDeployConfig, 0)
|
||||
for idx := 0; params.Contains(fmt.Sprintf("deploy.%d.path", idx)); idx += 1 {
|
||||
path, _ := params.GetString(fmt.Sprintf("deploy.%d.path", idx))
|
||||
action, _ := params.GetString(fmt.Sprintf("deploy.%d.action", idx))
|
||||
content, _ := params.GetString(fmt.Sprintf("deploy.%d.content", idx))
|
||||
deploys = append(deploys, SDeployConfig{Path: path, Action: action, Content: content})
|
||||
deploys, err := cmdline.FetchDeployConfigsByJSON(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(deploys) > 0 {
|
||||
@@ -3861,34 +3904,39 @@ func (self *SGuest) getDefaultStorageType() string {
|
||||
return STORAGE_LOCAL
|
||||
}
|
||||
|
||||
func (self *SGuest) getSchedDesc() jsonutils.JSONObject {
|
||||
desc := jsonutils.NewDict()
|
||||
func (self *SGuest) getSchedDesc() *schedapi.ScheduleInput {
|
||||
desc := new(schedapi.ScheduleInput)
|
||||
|
||||
desc.Add(jsonutils.NewString(self.Id), "id")
|
||||
desc.Add(jsonutils.NewString(self.Name), "name")
|
||||
desc.Add(jsonutils.NewInt(int64(self.VmemSize)), "vmem_size")
|
||||
desc.Add(jsonutils.NewInt(int64(self.VcpuCount)), "vcpu_count")
|
||||
desc.Id = self.Id
|
||||
desc.Name = self.Name
|
||||
desc.Memory = self.VmemSize
|
||||
desc.Ncpu = int(self.VcpuCount)
|
||||
|
||||
gds := self.GetDisks()
|
||||
if gds != nil {
|
||||
for i := 0; i < len(gds); i += 1 {
|
||||
desc.Add(jsonutils.Marshal(gds[i].ToDiskInfo()), fmt.Sprintf("disk.%d", i))
|
||||
conf := new(api.DiskConfig)
|
||||
jsonutils.Marshal(gds[i].ToDiskInfo()).Unmarshal(conf)
|
||||
desc.Disks = append(desc.Disks, conf)
|
||||
}
|
||||
}
|
||||
|
||||
gns, _ := self.GetNetworks("")
|
||||
if gns != nil {
|
||||
for i := 0; i < len(gns); i += 1 {
|
||||
desc.Add(jsonutils.NewString(fmt.Sprintf("%s:%s", gns[i].NetworkId, gns[i].IpAddr)), fmt.Sprintf("net.%d", i))
|
||||
desc.Networks = append(desc.Networks, &api.NetworkConfig{
|
||||
Network: gns[i].NetworkId,
|
||||
Address: gns[i].IpAddr,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(self.HostId) > 0 && regutils.MatchUUID(self.HostId) {
|
||||
desc.Add(jsonutils.NewString(self.HostId), "host_id")
|
||||
desc.HostId = self.HostId
|
||||
}
|
||||
|
||||
desc.Add(jsonutils.NewString(self.ProjectId), "owner_tenant_id")
|
||||
desc.Add(jsonutils.NewString(self.GetHypervisor()), "hypervisor")
|
||||
desc.Project = self.ProjectId
|
||||
desc.Hypervisor = self.GetHypervisor()
|
||||
|
||||
return desc
|
||||
}
|
||||
@@ -3901,28 +3949,31 @@ func (self *SGuest) GetApptags() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) ToSchedDesc() *jsonutils.JSONDict {
|
||||
desc := jsonutils.NewDict()
|
||||
desc.Set("id", jsonutils.NewString(self.Id))
|
||||
desc.Set("name", jsonutils.NewString(self.Name))
|
||||
desc.Set("vmem_size", jsonutils.NewInt(int64(self.VmemSize)))
|
||||
desc.Set("vcpu_count", jsonutils.NewInt(int64(self.VcpuCount)))
|
||||
self.FillGroupSchedDesc(desc)
|
||||
self.FillDiskSchedDesc(desc)
|
||||
self.FillNetSchedDesc(desc)
|
||||
if len(self.HostId) > 0 && regutils.MatchUUID(self.HostId) {
|
||||
desc.Set("host_id", jsonutils.NewString(self.HostId))
|
||||
func (self *SGuest) ToSchedDesc() *schedapi.ScheduleInput {
|
||||
desc := new(schedapi.ScheduleInput)
|
||||
config := &schedapi.ServerConfig{
|
||||
Name: self.Name,
|
||||
Memory: self.VmemSize,
|
||||
Ncpu: int(self.VcpuCount),
|
||||
}
|
||||
desc.Set("owner_tenant_id", jsonutils.NewString(self.ProjectId))
|
||||
tags := self.GetApptags()
|
||||
//self.FillGroupSchedDesc(desc)
|
||||
self.FillDiskSchedDesc(config)
|
||||
self.FillNetSchedDesc(config)
|
||||
if len(self.HostId) > 0 && regutils.MatchUUID(self.HostId) {
|
||||
config.HostId = self.HostId
|
||||
}
|
||||
config.Project = self.ProjectId
|
||||
/*tags := self.GetApptags()
|
||||
for i := 0; i < len(tags); i++ {
|
||||
desc.Set(tags[i], jsonutils.JSONTrue)
|
||||
}
|
||||
desc.Set("hypervisor", jsonutils.NewString(self.GetHypervisor()))
|
||||
}*/
|
||||
|
||||
config.Hypervisor = self.GetHypervisor()
|
||||
desc.ServerConfig = *config
|
||||
return desc
|
||||
}
|
||||
|
||||
func (self *SGuest) FillGroupSchedDesc(desc *jsonutils.JSONDict) {
|
||||
/*func (self *SGuest) FillGroupSchedDesc(desc *schedapi.ServerConfig) {
|
||||
groups := make([]SGroupguest, 0)
|
||||
err := GroupguestManager.Query().Equals("guest_id", self.Id).All(&groups)
|
||||
if err != nil {
|
||||
@@ -3933,31 +3984,29 @@ func (self *SGuest) FillGroupSchedDesc(desc *jsonutils.JSONDict) {
|
||||
desc.Set(fmt.Sprintf("srvtag.%d", i),
|
||||
jsonutils.NewString(fmt.Sprintf("%s:%s", groups[i].SrvtagId, groups[i].Tag)))
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
func (self *SGuest) FillDiskSchedDesc(desc *jsonutils.JSONDict) {
|
||||
func (self *SGuest) FillDiskSchedDesc(desc *schedapi.ServerConfig) {
|
||||
guestDisks := make([]SGuestdisk, 0)
|
||||
err := GuestdiskManager.Query().Equals("guest_id", self.Id).All(&guestDisks)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
log.Errorln("FillDiskSchedDesc: %v", err)
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(guestDisks); i++ {
|
||||
desc.Set(fmt.Sprintf("disk.%d", i), jsonutils.Marshal(guestDisks[i].ToDiskInfo()))
|
||||
desc.Disks = append(desc.Disks, guestDisks[i].ToDiskConfig())
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SGuest) FillNetSchedDesc(desc *jsonutils.JSONDict) {
|
||||
func (self *SGuest) FillNetSchedDesc(desc *schedapi.ServerConfig) {
|
||||
guestNetworks := make([]SGuestnetwork, 0)
|
||||
err := GuestnetworkManager.Query().Equals("guest_id", self.Id).All(&guestNetworks)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
log.Errorln("FillNetSchedDesc: %v", err)
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(guestNetworks); i++ {
|
||||
desc.Set(fmt.Sprintf("net.%d", i),
|
||||
jsonutils.NewString(fmt.Sprintf("%s:%s",
|
||||
guestNetworks[i].NetworkId, guestNetworks[i].IpAddr)))
|
||||
desc.Networks = append(desc.Networks, guestNetworks[i].ToNetworkConfig())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
@@ -38,23 +38,20 @@ func RunBatchCreateTask(
|
||||
}
|
||||
}
|
||||
|
||||
func ValidateScheduleCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, hypervisor string) (*jsonutils.JSONDict, error) {
|
||||
func ValidateScheduleCreateData(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput, hypervisor string) (*api.ServerCreateInput, error) {
|
||||
var err error
|
||||
|
||||
if jsonutils.QueryBoolean(data, "baremetal", false) {
|
||||
if input.Baremetal {
|
||||
hypervisor = HYPERVISOR_BAREMETAL
|
||||
}
|
||||
|
||||
// base validate_create_data
|
||||
if (data.Contains("prefer_baremetal") || data.Contains("prefer_host")) && hypervisor != HYPERVISOR_CONTAINER {
|
||||
if (input.PreferHost != "") && hypervisor != HYPERVISOR_CONTAINER {
|
||||
|
||||
if !userCred.IsAdminAllow(consts.GetServiceType(), GuestManager.KeywordPlural(), policy.PolicyActionPerform, "assign-host") {
|
||||
return nil, httperrors.NewNotSufficientPrivilegeError("Only system admin can specify preferred host")
|
||||
}
|
||||
bmName, _ := data.GetString("prefer_host")
|
||||
if len(bmName) == 0 {
|
||||
bmName, _ = data.GetString("prefer_baremetal")
|
||||
}
|
||||
bmName := input.PreferHost
|
||||
bmObj, err := HostManager.FetchByIdOrName(nil, bmName)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
@@ -80,45 +77,35 @@ func ValidateScheduleCreateData(ctx context.Context, userCred mcclient.TokenCred
|
||||
hypervisor = HYPERVISOR_DEFAULT
|
||||
}
|
||||
|
||||
_, err = GetDriver(hypervisor).ValidateCreateHostData(ctx, userCred, bmName, baremetal, data)
|
||||
_, err = GetDriver(hypervisor).ValidateCreateHostData(ctx, userCred, bmName, baremetal, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data.Set("prefer_baremetal_id", jsonutils.NewString(baremetal.Id))
|
||||
data.Set("prefer_host_id", jsonutils.NewString(baremetal.Id))
|
||||
input.PreferHost = baremetal.Id
|
||||
zone := baremetal.GetZone()
|
||||
data.Set("prefer_zone_id", jsonutils.NewString(zone.Id))
|
||||
input.PreferZone = zone.Id
|
||||
region := zone.GetRegion()
|
||||
data.Set("prefer_region_id", jsonutils.NewString(region.Id))
|
||||
input.PreferRegion = region.Id
|
||||
} else {
|
||||
schedtags := make(map[string]string)
|
||||
if data.Contains("aggregate_strategy") {
|
||||
err = data.Unmarshal(&schedtags, "aggregate_strategy")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid aggregate_strategy")
|
||||
}
|
||||
}
|
||||
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 {
|
||||
schedtags[parts[0]] = parts[1]
|
||||
}
|
||||
}
|
||||
for _, tag := range input.Schedtags {
|
||||
schedtags[tag.Id] = tag.Strategy
|
||||
}
|
||||
if len(schedtags) > 0 {
|
||||
schedtags, err = SchedtagManager.ValidateSchedtags(userCred, schedtags)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("invalid aggregate_strategy: %s", err)
|
||||
}
|
||||
data.Add(jsonutils.Marshal(schedtags), "aggregate_strategy")
|
||||
tags := make([]*api.SchedtagConfig, 0)
|
||||
for name, strategy := range schedtags {
|
||||
tags = append(tags, &api.SchedtagConfig{Id: name, Strategy: strategy})
|
||||
}
|
||||
input.Schedtags = tags
|
||||
}
|
||||
|
||||
if data.Contains("prefer_wire") {
|
||||
wireStr, _ := data.GetString("prefer_wire")
|
||||
if input.PreferWire != "" {
|
||||
wireStr := input.PreferWire
|
||||
wireObj, err := WireManager.FetchById(wireStr)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
@@ -128,13 +115,13 @@ func ValidateScheduleCreateData(ctx context.Context, userCred mcclient.TokenCred
|
||||
}
|
||||
}
|
||||
wire := wireObj.(*SWire)
|
||||
data.Set("prefer_wire_id", jsonutils.NewString(wire.Id))
|
||||
input.PreferWire = wire.Id
|
||||
zone := wire.GetZone()
|
||||
data.Set("prefer_zone_id", jsonutils.NewString(zone.Id))
|
||||
input.PreferZone = zone.Id
|
||||
region := zone.GetRegion()
|
||||
data.Set("prefer_region_id", jsonutils.NewString(region.Id))
|
||||
} else if data.Contains("prefer_zone") {
|
||||
zoneStr, _ := data.GetString("prefer_zone")
|
||||
input.PreferRegion = region.Id
|
||||
} else if input.PreferZone != "" {
|
||||
zoneStr := input.PreferZone
|
||||
zoneObj, err := ZoneManager.FetchById(zoneStr)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
@@ -144,11 +131,11 @@ func ValidateScheduleCreateData(ctx context.Context, userCred mcclient.TokenCred
|
||||
}
|
||||
}
|
||||
zone := zoneObj.(*SZone)
|
||||
data.Set("prefer_zone_id", jsonutils.NewString(zone.Id))
|
||||
input.PreferZone = zone.Id
|
||||
region := zone.GetRegion()
|
||||
data.Set("prefer_region_id", jsonutils.NewString(region.Id))
|
||||
} else if data.Contains("prefer_region") {
|
||||
regionStr, _ := data.GetString("prefer_region")
|
||||
input.PreferRegion = region.Id
|
||||
} else if input.PreferRegion != "" {
|
||||
regionStr := input.PreferRegion
|
||||
regionObj, err := CloudregionManager.FetchById(regionStr)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
@@ -158,7 +145,7 @@ func ValidateScheduleCreateData(ctx context.Context, userCred mcclient.TokenCred
|
||||
}
|
||||
}
|
||||
region := regionObj.(*SCloudregion)
|
||||
data.Set("prefer_region_id", jsonutils.NewString(region.Id))
|
||||
input.PreferRegion = region.Id
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,6 +158,6 @@ func ValidateScheduleCreateData(ctx context.Context, userCred mcclient.TokenCred
|
||||
return nil, httperrors.NewInputParameterError("Hypervisor %s not supported", hypervisor)
|
||||
}
|
||||
|
||||
data.Add(jsonutils.NewString(hypervisor), "hypervisor")
|
||||
return data, nil
|
||||
input.Hypervisor = hypervisor
|
||||
return input, nil
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
@@ -534,7 +535,7 @@ func (self *SHost) BorrowIpAddrsFromGuest(ctx context.Context, userCred mcclient
|
||||
return nil
|
||||
}
|
||||
|
||||
func (host *SHost) SetGuestCreateNetworkAndDiskParams(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
func (host *SHost) SetGuestCreateNetworkAndDiskParams(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
|
||||
ihost, err := host.GetIHost()
|
||||
if err != nil {
|
||||
log.Errorf("host.GetIHost fail %s", err)
|
||||
@@ -555,6 +556,7 @@ func (host *SHost) SetGuestCreateNetworkAndDiskParams(ctx context.Context, userC
|
||||
|
||||
netifs := host.GetNetInterfaces()
|
||||
netIdx := 0
|
||||
input.Networks = make([]*api.NetworkConfig, 0)
|
||||
for i := 0; i < len(netifs); i += 1 {
|
||||
hn := netifs[i].GetBaremetalNetwork()
|
||||
if hn != nil {
|
||||
@@ -563,12 +565,15 @@ func (host *SHost) SetGuestCreateNetworkAndDiskParams(ctx context.Context, userC
|
||||
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))
|
||||
input.Networks = append(input.Networks, &api.NetworkConfig{
|
||||
Network: hn.NetworkId,
|
||||
Mac: packedMac,
|
||||
Address: hn.IpAddr,
|
||||
})
|
||||
netIdx += 1
|
||||
}
|
||||
}
|
||||
params.Set(fmt.Sprintf("net.%d", netIdx), jsonutils.JSONNull)
|
||||
//params.Set(fmt.Sprintf("net.%d", netIdx), jsonutils.JSONNull)
|
||||
|
||||
for i := 0; i < len(idisks); i += 1 {
|
||||
/*istorage, err := idisks[i].GetIStorage()
|
||||
@@ -577,31 +582,34 @@ func (host *SHost) SetGuestCreateNetworkAndDiskParams(ctx context.Context, userC
|
||||
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)
|
||||
var diskConfig *api.DiskConfig
|
||||
if i < len(input.Disks) {
|
||||
diskConfig = input.Disks[i]
|
||||
diskConfig, err := parseDiskInfo(ctx, userCred, diskConfig)
|
||||
if err != nil {
|
||||
log.Debugf("parseDiskInfo %s fail %s", jsonConf, err)
|
||||
log.Debugf("parseDiskInfo %s fail %s", diskConfig, err)
|
||||
return nil, err
|
||||
}
|
||||
conf.SizeMb = idisks[i].GetDiskSizeMB()
|
||||
conf.Backend = STORAGE_LOCAL
|
||||
params.Set(key, jsonutils.Marshal(conf))
|
||||
diskConfig.SizeMb = idisks[i].GetDiskSizeMB()
|
||||
diskConfig.Backend = STORAGE_LOCAL
|
||||
input.Disks[i] = diskConfig
|
||||
} else {
|
||||
strConf := fmt.Sprintf("%s:%d", STORAGE_LOCAL, idisks[i].GetDiskSizeMB())
|
||||
conf, err := parseDiskInfo(ctx, userCred, jsonutils.NewString(strConf))
|
||||
conf := &api.DiskConfig{
|
||||
SizeMb: idisks[i].GetDiskSizeMB(),
|
||||
Backend: STORAGE_LOCAL,
|
||||
}
|
||||
conf, err = parseDiskInfo(ctx, userCred, conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Set(key, jsonutils.Marshal(conf))
|
||||
input.Disks = append(input.Disks, conf)
|
||||
}
|
||||
}
|
||||
params.Set(fmt.Sprintf("disk.%d", len(idisks)), jsonutils.JSONNull)
|
||||
//params.Set(fmt.Sprintf("disk.%d", len(idisks)), jsonutils.JSONNull)
|
||||
|
||||
// log.Debugf("params after rebuid: %s", params.String())
|
||||
|
||||
return params, nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (host *SHost) RebuildRecycledGuest(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest) error {
|
||||
|
||||
+51
-63
@@ -21,6 +21,7 @@ import (
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
@@ -37,68 +38,68 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
HOST_TYPE_BAREMETAL = "baremetal"
|
||||
HOST_TYPE_HYPERVISOR = "hypervisor" // KVM
|
||||
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_BAREMETAL = api.HOST_TYPE_BAREMETAL
|
||||
HOST_TYPE_HYPERVISOR = api.HOST_TYPE_HYPERVISOR // KVM
|
||||
HOST_TYPE_KVM = api.HOST_TYPE_KVM
|
||||
HOST_TYPE_ESXI = api.HOST_TYPE_ESXI // # VMWare vSphere ESXi
|
||||
HOST_TYPE_KUBELET = api.HOST_TYPE_KUBELET // # Kubernetes Kubelet
|
||||
HOST_TYPE_HYPERV = api.HOST_TYPE_HYPERV // # Microsoft Hyper-V
|
||||
HOST_TYPE_XEN = api.HOST_TYPE_XEN // # XenServer
|
||||
|
||||
HOST_TYPE_ALIYUN = "aliyun"
|
||||
HOST_TYPE_AWS = "aws"
|
||||
HOST_TYPE_QCLOUD = "qcloud"
|
||||
HOST_TYPE_AZURE = "azure"
|
||||
HOST_TYPE_HUAWEI = "huawei"
|
||||
HOST_TYPE_OPENSTACK = "openstack"
|
||||
HOST_TYPE_UCLOUD = "ucloud"
|
||||
HOST_TYPE_ALIYUN = api.HOST_TYPE_ALIYUN
|
||||
HOST_TYPE_AWS = api.HOST_TYPE_AWS
|
||||
HOST_TYPE_QCLOUD = api.HOST_TYPE_QCLOUD
|
||||
HOST_TYPE_AZURE = api.HOST_TYPE_AZURE
|
||||
HOST_TYPE_HUAWEI = api.HOST_TYPE_HUAWEI
|
||||
HOST_TYPE_OPENSTACK = api.HOST_TYPE_OPENSTACK
|
||||
HOST_TYPE_UCLOUD = api.HOST_TYPE_UCLOUD
|
||||
|
||||
HOST_TYPE_DEFAULT = HOST_TYPE_HYPERVISOR
|
||||
|
||||
// # possible status
|
||||
HOST_ONLINE = "online"
|
||||
HOST_ENABLED = "online"
|
||||
HOST_OFFLINE = "offline"
|
||||
HOST_DISABLED = "offline"
|
||||
HOST_ONLINE = api.HOST_ONLINE
|
||||
HOST_ENABLED = api.HOST_ENABLED
|
||||
HOST_OFFLINE = api.HOST_OFFLINE
|
||||
HOST_DISABLED = api.HOST_DISABLED
|
||||
|
||||
NIC_TYPE_IPMI = "ipmi"
|
||||
NIC_TYPE_ADMIN = "admin"
|
||||
NIC_TYPE_IPMI = api.NIC_TYPE_IPMI
|
||||
NIC_TYPE_ADMIN = api.NIC_TYPE_ADMIN
|
||||
// #NIC_TYPE_NORMAL = 'normal'
|
||||
|
||||
BAREMETAL_INIT = "init"
|
||||
BAREMETAL_PREPARE = "prepare"
|
||||
BAREMETAL_PREPARE_FAIL = "prepare_fail"
|
||||
BAREMETAL_READY = "ready"
|
||||
BAREMETAL_RUNNING = "running"
|
||||
BAREMETAL_MAINTAINING = "maintaining"
|
||||
BAREMETAL_START_MAINTAIN = "start_maintain"
|
||||
BAREMETAL_DELETING = "deleting"
|
||||
BAREMETAL_DELETE = "delete"
|
||||
BAREMETAL_DELETE_FAIL = "delete_fail"
|
||||
BAREMETAL_UNKNOWN = "unknown"
|
||||
BAREMETAL_SYNCING_STATUS = "syncing_status"
|
||||
BAREMETAL_SYNC = "sync"
|
||||
BAREMETAL_SYNC_FAIL = "sync_fail"
|
||||
BAREMETAL_START_CONVERT = "start_convert"
|
||||
BAREMETAL_CONVERTING = "converting"
|
||||
BAREMETAL_START_FAIL = "start_fail"
|
||||
BAREMETAL_STOP_FAIL = "stop_fail"
|
||||
BAREMETAL_INIT = api.BAREMETAL_INIT
|
||||
BAREMETAL_PREPARE = api.BAREMETAL_PREPARE
|
||||
BAREMETAL_PREPARE_FAIL = api.BAREMETAL_PREPARE_FAIL
|
||||
BAREMETAL_READY = api.BAREMETAL_READY
|
||||
BAREMETAL_RUNNING = api.BAREMETAL_RUNNING
|
||||
BAREMETAL_MAINTAINING = api.BAREMETAL_MAINTAINING
|
||||
BAREMETAL_START_MAINTAIN = api.BAREMETAL_START_MAINTAIN
|
||||
BAREMETAL_DELETING = api.BAREMETAL_DELETING
|
||||
BAREMETAL_DELETE = api.BAREMETAL_DELETE
|
||||
BAREMETAL_DELETE_FAIL = api.BAREMETAL_DELETE_FAIL
|
||||
BAREMETAL_UNKNOWN = api.BAREMETAL_UNKNOWN
|
||||
BAREMETAL_SYNCING_STATUS = api.BAREMETAL_SYNCING_STATUS
|
||||
BAREMETAL_SYNC = api.BAREMETAL_SYNC
|
||||
BAREMETAL_SYNC_FAIL = api.BAREMETAL_SYNC_FAIL
|
||||
BAREMETAL_START_CONVERT = api.BAREMETAL_START_CONVERT
|
||||
BAREMETAL_CONVERTING = api.BAREMETAL_CONVERTING
|
||||
BAREMETAL_START_FAIL = api.BAREMETAL_START_FAIL
|
||||
BAREMETAL_STOP_FAIL = api.BAREMETAL_STOP_FAIL
|
||||
|
||||
HOST_STATUS_RUNNING = BAREMETAL_RUNNING
|
||||
HOST_STATUS_READY = BAREMETAL_READY
|
||||
HOST_STATUS_UNKNOWN = BAREMETAL_UNKNOWN
|
||||
HOST_STATUS_RUNNING = api.BAREMETAL_RUNNING
|
||||
HOST_STATUS_READY = api.BAREMETAL_READY
|
||||
HOST_STATUS_UNKNOWN = api.BAREMETAL_UNKNOWN
|
||||
)
|
||||
|
||||
const (
|
||||
HostResourceTypeShared = "shared"
|
||||
HostResourceTypeDefault = HostResourceTypeShared
|
||||
HostResourceTypePrepaidRecycle = "prepaid"
|
||||
HostResourceTypeDedicated = "dedicated"
|
||||
HostResourceTypeShared = api.HostResourceTypeShared
|
||||
HostResourceTypeDefault = api.HostResourceTypeShared
|
||||
HostResourceTypePrepaidRecycle = api.HostResourceTypePrepaidRecycle
|
||||
HostResourceTypeDedicated = api.HostResourceTypeDedicated
|
||||
)
|
||||
|
||||
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, HOST_TYPE_HUAWEI, HOST_TYPE_OPENSTACK}
|
||||
var HOST_TYPES = api.HOST_TYPES
|
||||
|
||||
var NIC_TYPES = []string{NIC_TYPE_IPMI, NIC_TYPE_ADMIN}
|
||||
var NIC_TYPES = api.NIC_TYPES
|
||||
|
||||
type SHostManager struct {
|
||||
db.SEnabledStatusStandaloneResourceBaseManager
|
||||
@@ -2079,20 +2080,8 @@ func (self *SHost) GetBaremetalServer() *SGuest {
|
||||
return &guest
|
||||
}
|
||||
|
||||
func (self *SHost) getSchedtags() []SSchedtag {
|
||||
tags := make([]SSchedtag, 0)
|
||||
schedtags := SchedtagManager.Query().SubQuery()
|
||||
hostschedtags := HostschedtagManager.Query().SubQuery()
|
||||
q := schedtags.Query()
|
||||
q = q.Join(hostschedtags, sqlchemy.AND(sqlchemy.Equals(hostschedtags.Field("schedtag_id"), schedtags.Field("id")),
|
||||
sqlchemy.IsFalse(hostschedtags.Field("deleted"))))
|
||||
q = q.Filter(sqlchemy.Equals(hostschedtags.Field("host_id"), self.Id))
|
||||
err := db.FetchModelObjects(SchedtagManager, q, &tags)
|
||||
if err != nil {
|
||||
log.Errorf("%s", err)
|
||||
return nil
|
||||
}
|
||||
return tags
|
||||
func (self *SHost) GetSchedtags() []SSchedtag {
|
||||
return GetSchedtags(HostschedtagManager, self.Id)
|
||||
}
|
||||
|
||||
type SHostGuestResourceUsage struct {
|
||||
@@ -2158,7 +2147,7 @@ func (self *SHost) getMoreDetails(ctx context.Context, extra *jsonutils.JSONDict
|
||||
extra.Add(jsonutils.NewInt(int64(len(nicInfos))), "nic_count")
|
||||
extra.Add(jsonutils.NewArray(nicInfos...), "nic_info")
|
||||
}
|
||||
schedtags := self.getSchedtags()
|
||||
schedtags := self.GetSchedtags()
|
||||
if schedtags != nil && len(schedtags) > 0 {
|
||||
info := make([]jsonutils.JSONObject, len(schedtags))
|
||||
for i := 0; i < len(schedtags); i += 1 {
|
||||
@@ -3033,7 +3022,6 @@ func (self *SHost) EnableNetif(ctx context.Context, userCred mcclient.TokenCrede
|
||||
if bn != nil {
|
||||
return nil
|
||||
}
|
||||
log.Errorf("==========EnableNetif %#v, net: %s, ipAddr: %s, allocDir: %s, reserve: %v, requireDesignatedIp: %v", netif, network, ipAddr, allocDir, reserve, requireDesignatedIp)
|
||||
var net *SNetwork
|
||||
var err error
|
||||
if len(ipAddr) > 0 {
|
||||
|
||||
@@ -4,14 +4,13 @@ import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
type SHostschedtagManager struct {
|
||||
SHostJointsManager
|
||||
*SSchedtagJointsManager
|
||||
}
|
||||
|
||||
var HostschedtagManager *SHostschedtagManager
|
||||
@@ -19,11 +18,12 @@ var HostschedtagManager *SHostschedtagManager
|
||||
func init() {
|
||||
db.InitManager(func() {
|
||||
HostschedtagManager = &SHostschedtagManager{
|
||||
SHostJointsManager: NewHostJointsManager(
|
||||
SSchedtagJointsManager: NewSchedtagJointsManager(
|
||||
SHostschedtag{},
|
||||
"aggregate_hosts_tbl",
|
||||
"schedtaghost",
|
||||
"schedtaghosts",
|
||||
HostManager,
|
||||
SchedtagManager,
|
||||
),
|
||||
}
|
||||
@@ -31,55 +31,37 @@ func init() {
|
||||
}
|
||||
|
||||
type SHostschedtag struct {
|
||||
SHostJointsBase
|
||||
SSchedtagJointsBase
|
||||
|
||||
HostId string `width:"36" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(36, charset='ascii'), nullable=False)
|
||||
SchedtagId string `width:"36" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // =Column(VARCHAR(36, charset='ascii'), nullable=False)
|
||||
HostId string `width:"36" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(36, charset='ascii'), nullable=False)
|
||||
}
|
||||
|
||||
func (joint *SHostschedtag) Master() db.IStandaloneModel {
|
||||
return db.JointMaster(joint)
|
||||
func (self *SHostschedtag) GetHost() *SHost {
|
||||
return self.Master().(*SHost)
|
||||
}
|
||||
|
||||
func (joint *SHostschedtag) Slave() db.IStandaloneModel {
|
||||
return db.JointSlave(joint)
|
||||
func (self *SHostschedtag) GetHosts() ([]SHost, error) {
|
||||
hosts := []SHost{}
|
||||
err := self.GetSchedtag().GetObjects(&hosts)
|
||||
return hosts, err
|
||||
}
|
||||
|
||||
func (self *SHostschedtag) Master() db.IStandaloneModel {
|
||||
return self.SSchedtagJointsBase.master(self)
|
||||
}
|
||||
|
||||
func (self *SHostschedtag) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
extra := self.SHostJointsBase.GetCustomizeColumns(ctx, userCred, query)
|
||||
return db.JointModelExtra(self, extra)
|
||||
return self.SSchedtagJointsBase.getCustomizeColumns(self, ctx, userCred, query)
|
||||
}
|
||||
|
||||
func (self *SHostschedtag) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
|
||||
extra, err := self.SHostJointsBase.GetExtraDetails(ctx, userCred, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return db.JointModelExtra(self, extra), nil
|
||||
}
|
||||
|
||||
func (self *SHostschedtag) getHost() *SHost {
|
||||
obj, err := HostManager.FetchById(self.HostId)
|
||||
if err != nil {
|
||||
log.Errorf("%s", err)
|
||||
return nil
|
||||
}
|
||||
return obj.(*SHost)
|
||||
}
|
||||
|
||||
func (self *SHostschedtag) getSchedtag() *SSchedtag {
|
||||
obj, err := SchedtagManager.FetchById(self.SchedtagId)
|
||||
if err != nil {
|
||||
log.Errorf("%s", err)
|
||||
return nil
|
||||
}
|
||||
return obj.(*SSchedtag)
|
||||
return self.SSchedtagJointsBase.getExtraDetails(self, ctx, userCred, query)
|
||||
}
|
||||
|
||||
func (self *SHostschedtag) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DeleteModel(ctx, userCred, self)
|
||||
return self.SSchedtagJointsBase.delete(self, ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SHostschedtag) Detach(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DetachJoint(ctx, userCred, self)
|
||||
return self.SSchedtagJointsBase.detach(self, ctx, userCred)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user