fix conflict

This commit is contained in:
TangBin
2019-03-20 15:18:35 +08:00
277 changed files with 6742 additions and 4529 deletions
Generated
+2 -2
View File
@@ -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"
+9
View File
@@ -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
})
}
+3 -19
View File
@@ -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
}
+4
View File
@@ -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")
}
+22
View File
@@ -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
})
}
+75 -48
View File
@@ -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()
}
+10 -2
View File
@@ -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
+5 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -1 +0,0 @@
package app // import "yunion.io/x/onecloud/cmd/scheduler/app"
-107
View File
@@ -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
}
+2 -2
View File
@@ -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
View File
@@ -1 +0,0 @@
package options // import "yunion.io/x/onecloud/cmd/scheduler/options"
+12
View File
@@ -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)
}
+178
View File
@@ -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"`
}
+54
View File
@@ -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)
)
+51
View File
@@ -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,
}
}
+40
View File
@@ -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"
)
+1
View File
@@ -0,0 +1 @@
package compute // import "yunion.io/x/onecloud/pkg/apis/compute"
+65
View File
@@ -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}
+26
View File
@@ -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"
+38
View File
@@ -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,
}
)
+13
View File
@@ -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}
+82
View File
@@ -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}
)
+1
View File
@@ -0,0 +1 @@
package apis // import "yunion.io/x/onecloud/pkg/apis"
+82
View File
@@ -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"`
}
+1
View File
@@ -0,0 +1 @@
package scheduler // import "yunion.io/x/onecloud/pkg/apis/scheduler"
+9 -1
View File
@@ -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 {
+2 -1
View File
@@ -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 {
+2 -4
View File
@@ -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"`
+4 -4
View File
@@ -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
}
-2
View File
@@ -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)
+13
View File
@@ -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 {
+6 -5
View File
@@ -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 -2
View File
@@ -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 -9
View File
@@ -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
}
+7 -6
View File
@@ -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
}
+24 -23
View File
@@ -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 -7
View File
@@ -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
}
+8 -7
View File
@@ -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")
+1
View File
@@ -0,0 +1 @@
package app // import "yunion.io/x/onecloud/pkg/cloudcommon/app"
+1
View File
@@ -0,0 +1 @@
package cmdline // import "yunion.io/x/onecloud/pkg/cloudcommon/cmdline"
+406
View File
@@ -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
}
+87
View File
@@ -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)
}
})
}
}
+349
View File
@@ -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
}
+177
View File
@@ -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)
}
})
}
}
+2 -1
View File
@@ -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()
}
+3 -1
View File
@@ -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
View File
@@ -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)
}
+114 -1
View File
@@ -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")
+1
View File
@@ -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)
}
+1
View File
@@ -0,0 +1 @@
package options // import "yunion.io/x/onecloud/pkg/cloudcommon/options"
@@ -1,4 +1,4 @@
package cloudcommon
package options
import (
"fmt"
-1
View File
@@ -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}
)
+2 -2
View File
@@ -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 (
+7 -5
View File
@@ -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()
})
}
+1 -1
View File
@@ -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)
}
}
+2 -2
View File
@@ -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 (
+7 -5
View File
@@ -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)
}
+22 -166
View File
@@ -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
+10 -57
View File
@@ -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)
}
+24 -63
View File
@@ -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"`
+1 -1
View File
@@ -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
View File
@@ -1 +0,0 @@
package consts
-1
View File
@@ -1 +0,0 @@
package consts // import "yunion.io/x/onecloud/pkg/compute/consts"
+17 -17
View File
@@ -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 {
+14 -10
View File
@@ -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 {
+22 -12
View File
@@ -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 {
+39 -43
View File
@@ -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 {
-14
View File
@@ -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)
}
+5 -7
View File
@@ -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)
+4 -1
View File
@@ -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 {
+11 -5
View File
@@ -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 {
+20 -20
View File
@@ -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 {
+15 -10
View File
@@ -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 {
+4 -3
View File
@@ -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 {
+1
View File
@@ -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")
+1 -12
View File
@@ -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")
+70 -33
View File
@@ -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
+29 -5
View File
@@ -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)
}
}
})
}
+27 -16
View File
@@ -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())
}
+45 -10
View File
@@ -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()
}
+36
View File
@@ -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
}
+1 -1
View File
@@ -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
View File
@@ -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")
+10 -2
View File
@@ -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 {
+59 -38
View File
@@ -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
}
+12
View File
@@ -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 -5
View File
@@ -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
View File
@@ -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
View File
@@ -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())
}
}
+30 -43
View File
@@ -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
}
+25 -17
View File
@@ -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
View File
@@ -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 {
+19 -37
View File
@@ -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