diff --git a/pkg/compute/baremetal/diskconfig_test.go b/pkg/compute/baremetal/diskconfig_test.go index 93b06d6779..5b29531b45 100644 --- a/pkg/compute/baremetal/diskconfig_test.go +++ b/pkg/compute/baremetal/diskconfig_test.go @@ -19,7 +19,6 @@ import ( "reflect" "testing" - "yunion.io/x/log" api "yunion.io/x/onecloud/pkg/apis/compute" ) @@ -491,10 +490,6 @@ func TestCheckDisksAllocable(t *testing.T) { t.Fatalf("Calculate bitmain layout err: %v", err) } - log.Debugf("defaultLayout: %s", defaultLayout) - log.Debugf("layout: %s", layout) - log.Debugf("Bitmain layout: %s", bitmainLayout) - tdiskDefault := []*Disk{ {Size: -1}, {Size: -1}, @@ -949,11 +944,10 @@ func TestStorageLoad(t *testing.T) { t.Fatalf("NewDiskConfigs err: %v", err) } json.Unmarshal([]byte(testStorages2), &ss) - layout, err := CalculateLayout(confs, ss) + _, err = CalculateLayout(confs, ss) if err != nil { t.Fatalf("CalculateLayout err: %v", err) } - log.Debugf("layout: %s", layout) } func TestCalculateSize(t *testing.T) { @@ -1132,3 +1126,123 @@ func TestValidateDiskConfigs(t *testing.T) { }) } } + +func TestRetrieveStorages(t *testing.T) { + type args struct { + diskConfig *api.BaremetalDiskConfig + storages []*BaremetalStorage + } + s1 := &BaremetalStorage{ + Size: 1, + Driver: "MegaRaid", + Adapter: 0, + } + s2 := &BaremetalStorage{ + Size: 1, + Driver: "MegaRaid", + Adapter: 0, + } + s3 := &BaremetalStorage{ + Size: 2, + Driver: "MegaRaid", + Adapter: 0, + } + tests := []struct { + name string + args args + wantSelected []*BaremetalStorage + wantRest []*BaremetalStorage + }{ + { + name: "select all", + args: args{ + diskConfig: &api.BaremetalDiskConfig{ + Driver: "MegaRaid", + Count: 0, + Type: api.DISK_TYPE_HYBRID, + }, + storages: []*BaremetalStorage{s1, s2, s3}, + }, + wantSelected: []*BaremetalStorage{s1, s2, s3}, + wantRest: []*BaremetalStorage{}, + }, + { + name: "select count 2", + args: args{ + diskConfig: &api.BaremetalDiskConfig{ + Driver: "MegaRaid", + Count: 2, + Type: api.DISK_TYPE_HYBRID, + }, + storages: []*BaremetalStorage{s1, s2, s3}, + }, + wantSelected: []*BaremetalStorage{s1, s2}, + wantRest: []*BaremetalStorage{s3}, + }, + { + name: "select by range", + args: args{ + diskConfig: &api.BaremetalDiskConfig{ + Driver: "MegaRaid", + Range: []int64{1, 2}, + Type: api.DISK_TYPE_HYBRID, + }, + storages: []*BaremetalStorage{s1, s2, s3}, + }, + wantSelected: []*BaremetalStorage{s2, s3}, + wantRest: []*BaremetalStorage{s1}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotSelected, gotRest := RetrieveStorages(tt.args.diskConfig, tt.args.storages) + if !reflect.DeepEqual(gotSelected, tt.wantSelected) { + t.Errorf("RetrieveStorages() gotSelected = %v, want %v", gotSelected, tt.wantSelected) + } + if !reflect.DeepEqual(gotRest, tt.wantRest) { + t.Errorf("RetrieveStorages() gotRest = %v, want %v", gotRest, tt.wantRest) + } + }) + } +} + +func TestGetSplitSizes(t *testing.T) { + type args struct { + size int64 + splitConf string + } + var totalSize int64 = 22889472 + size10p := int64(float64(totalSize) * 0.1) + tests := []struct { + name string + args args + want []int64 + }{ + { + name: "split gb", + args: args{ + size: totalSize, + splitConf: "60g,", + }, + want: []int64{61440, totalSize - 61440}, + }, + { + name: "split by percent", + args: args{ + size: totalSize, + splitConf: "10%,", + }, + want: []int64{ + size10p, + totalSize - size10p, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := GetSplitSizes(tt.args.size, tt.args.splitConf); !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetSplitSizes() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/compute/hostdrivers/base.go b/pkg/compute/hostdrivers/base.go index bde4003e95..9d1674bc55 100644 --- a/pkg/compute/hostdrivers/base.go +++ b/pkg/compute/hostdrivers/base.go @@ -66,21 +66,24 @@ func (self *SBaseHostDriver) RequestCleanUpDiskSnapshots(ctx context.Context, ho return fmt.Errorf("Not Implement") } -func (self *SBaseHostDriver) PrepareConvert(host *models.SHost, image, raid string, data jsonutils.JSONObject) (*jsonutils.JSONDict, error) { - params := jsonutils.NewDict() - params.Set("description", jsonutils.NewString("Baremetal convered Hypervisor")) - name, err := data.Get("name") +func (self *SBaseHostDriver) PrepareConvert(host *models.SHost, image, raid string, data jsonutils.JSONObject) (*api.ServerCreateInput, error) { + params := &api.ServerCreateInput{ + ServerConfigs: &api.ServerConfigs{ + PreferHost: host.Id, + }, + Description: "Baremetal convered Hypervisor", + VcpuCount: int(host.CpuCount), + VmemSize: host.MemSize, + AutoStart: true, + IsSystem: true, + Baremetal: true, + } + name, err := data.GetString("name") if err == nil { - params.Set("name", name) + params.Name = name } else { - params.Set("name", jsonutils.NewString(host.Name)) + params.Name = host.Name } - params.Set("vcpu_count", jsonutils.NewInt(int64(host.CpuCount))) - params.Set("vmem_size", jsonutils.NewInt(int64(host.MemSize))) - params.Set("auto_start", jsonutils.NewBool(true)) - params.Set("is_system", jsonutils.NewBool(true)) - params.Set("prefer_baremetal", jsonutils.NewString(host.Id)) - params.Set("baremetal", jsonutils.NewBool(true)) return params, nil } diff --git a/pkg/compute/hostdrivers/kvm.go b/pkg/compute/hostdrivers/kvm.go index 3270f713c0..331efad8ee 100644 --- a/pkg/compute/hostdrivers/kvm.go +++ b/pkg/compute/hostdrivers/kvm.go @@ -24,6 +24,7 @@ import ( "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/taskman" "yunion.io/x/onecloud/pkg/compute/baremetal" "yunion.io/x/onecloud/pkg/compute/models" @@ -351,66 +352,80 @@ func (self *SKVMHostDriver) RequestCleanUpDiskSnapshots(ctx context.Context, hos return err } -func (self *SKVMHostDriver) PrepareConvert(host *models.SHost, image, raid string, data jsonutils.JSONObject) (*jsonutils.JSONDict, error) { +func (self *SKVMHostDriver) PrepareConvert(host *models.SHost, image, raid string, data jsonutils.JSONObject) (*api.ServerCreateInput, error) { params, err := self.SBaseHostDriver.PrepareConvert(host, image, raid, data) 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") - for i := 0; i < len(jsonArray); i += 1 { // } .Contains(fmt.Sprintf("baremetal_disk_config.%d", i)); i++ { - // v, _ := data.Get(fmt.Sprintf("baremetal_disk_config.%d", i)) - params.Set(fmt.Sprintf("baremetal_disk_config.%d", i), jsonArray[i]) - } - } else { + raidConfs, _ := cmdline.FetchBaremetalDiskConfigsByJSON(data) + if len(raidConfs) == 0 { raid, err = self.GetRaidScheme(host, raid) if err != nil { return nil, err } if raid != baremetal.DISK_CONF_NONE { - params.Set("baremetal_disk_config.0", jsonutils.NewString(fmt.Sprintf("%s:(%s,)", raid, sysSize))) + raidConfs = []*api.BaremetalDiskConfig{ + { + Conf: raid, + Splits: fmt.Sprintf("%s,", sysSize), + Type: api.DISK_TYPE_HYBRID, + }, + } } } - if data.Contains("disk.0") { - jsonArray := jsonutils.GetArrayOfPrefix(data, "disk") - for i := 0; i < len(jsonArray); i += 1 { // } data.Contains(fmt.Sprintf("disk.%d", i)); i++ { - // v, _ := data.Get(fmt.Sprintf("disk.%d", i)) - params.Set(fmt.Sprintf("disk.%d", i), jsonArray[i]) - } - } else { + params.BaremetalDiskConfigs = raidConfs + disks, _ := cmdline.FetchDiskConfigsByJSON(data) + if len(disks) == 0 { if len(image) == 0 { image = options.Options.ConvertHypervisorDefaultTemplate } if len(image) == 0 { return nil, fmt.Errorf("Not default image specified for converting %s", self.GetHostType()) } + rootDisk := &api.DiskConfig{} if raid != baremetal.DISK_CONF_NONE { - params.Set("disk.0", jsonutils.NewString(fmt.Sprintf("%s:autoextend", image))) + rootDisk = &api.DiskConfig{ + ImageId: image, + SizeMb: -1, + } } else if host.StorageInfo.(*jsonutils.JSONArray).Length() > 1 { - params.Set("disk.0", jsonutils.NewString(fmt.Sprintf("%s:autoextend", image))) + rootDisk = &api.DiskConfig{ + ImageId: image, + SizeMb: -1, + } } else { - params.Set("disk.0", jsonutils.NewString(fmt.Sprintf("%s:%s", image, sysSize))) + rootDisk = &api.DiskConfig{ + ImageId: image, + SizeMb: 60 * 1024, // 60g + } } - params.Set("disk.1", jsonutils.NewString("ext4:autoextend:/opt/cloud/workspace")) + optDisk := &api.DiskConfig{ + Fs: "ext4", + SizeMb: -1, + Mountpoint: "/opt/cloud/workspace", + } + disks = append(disks, rootDisk, optDisk) } - if data.Contains("net.0") { - jsonArray := jsonutils.GetArrayOfPrefix(data, "net") - for i := 0; i < len(jsonArray); i += 1 { // } data.Contains(fmt.Sprintf("net.%d", i)); i++ { - // v, _ := data.Get(fmt.Sprintf("net.%d", i)) - params.Set(fmt.Sprintf("net.%d", i), jsonArray[i]) - } - } else { + params.Disks = disks + nets, _ := cmdline.FetchNetworkConfigsByJSON(data) + if len(nets) == 0 { wire := host.GetMasterWire() if wire == nil { return nil, fmt.Errorf("No master wire?") } - params.Set("net.0", jsonutils.NewString(fmt.Sprintf("wire=%s:[private]:[try-teaming]", wire.GetName()))) + net := &api.NetworkConfig{ + Wire: wire.GetId(), + Private: true, + TryTeaming: true, + } + nets = append(nets, net) + } + params.Networks = nets + deployConf := &api.DeployConfig{ + Action: "create", + Path: "/etc/sysconfig/yunionauth", } - params.Set("deploy.0.path", jsonutils.NewString("/etc/sysconfig/yunionauth")) - params.Set("deploy.0.action", jsonutils.NewString("create")) - log.Infof("%v", params) authLoc, err := url.Parse(options.Options.AuthURL) if err != nil { return nil, err @@ -437,7 +452,9 @@ func (self *SKVMHostDriver) PrepareConvert(host *models.SHost, image, raid strin authInfo += fmt.Sprintf("YUNION_HOST_PASSWORD=%s\n", options.Options.AdminPassword) authInfo += fmt.Sprintf("YUNION_HOST_PROJECT=%s\n", options.Options.AdminProject) authInfo += fmt.Sprintf("YUNION_START=yes\n") - params.Set("deploy.0.content", jsonutils.NewString(authInfo)) + deployConf.Content = authInfo + params.DeployConfigs = []*api.DeployConfig{deployConf} + log.Infof("%v", params) return params, nil } diff --git a/pkg/compute/models/hostdrivers.go b/pkg/compute/models/hostdrivers.go index 7c5e132c4c..c23a354579 100644 --- a/pkg/compute/models/hostdrivers.go +++ b/pkg/compute/models/hostdrivers.go @@ -20,6 +20,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/taskman" "yunion.io/x/onecloud/pkg/mcclient" ) @@ -48,7 +49,7 @@ type IHostDriver interface { RequestDeleteSnapshotsWithStorage(ctx context.Context, host *SHost, snapshot *SSnapshot, task taskman.ITask) error RequestResetDisk(ctx context.Context, host *SHost, disk *SDisk, params *jsonutils.JSONDict, task taskman.ITask) error RequestCleanUpDiskSnapshots(ctx context.Context, host *SHost, disk *SDisk, params *jsonutils.JSONDict, task taskman.ITask) error - PrepareConvert(host *SHost, image, raid string, data jsonutils.JSONObject) (*jsonutils.JSONDict, error) + PrepareConvert(host *SHost, image, raid string, data jsonutils.JSONObject) (*api.ServerCreateInput, error) PrepareUnconvert(host *SHost) error FinishUnconvert(ctx context.Context, userCred mcclient.TokenCredential, host *SHost) error FinishConvert(userCred mcclient.TokenCredential, host *SHost, guest *SGuest, hostType string) error diff --git a/pkg/compute/models/hosts.go b/pkg/compute/models/hosts.go index d67edf0c9d..68bc1406d5 100644 --- a/pkg/compute/models/hosts.go +++ b/pkg/compute/models/hosts.go @@ -3489,10 +3489,11 @@ func (self *SHost) PerformConvertHypervisor(ctx context.Context, userCred mcclie } image, _ := data.GetString("image") raid, _ := data.GetString("raid") - params, err := driver.PrepareConvert(self, image, raid, data) + input, err := driver.PrepareConvert(self, image, raid, data) if err != nil { return nil, httperrors.NewNotAcceptableError("Convert error: %s", err.Error()) } + params := input.JSON(input) ownerProjId := userCred.GetProjectId() guest, err := db.DoCreate(GuestManager, ctx, userCred, nil, params, ownerProjId) if err != nil { diff --git a/pkg/compute/options/options.go b/pkg/compute/options/options.go index 114f7600c4..63d733a9f6 100644 --- a/pkg/compute/options/options.go +++ b/pkg/compute/options/options.go @@ -80,8 +80,8 @@ type ComputeOptions struct { // aws instance type file DefaultAwsInstanceTypeFile string `default:"/etc/yunion/aws_instance_types.json" help:"aws instance type json file"` - ConvertHypervisorDefaultTemplate string `default:"Default template" help:"Kvm baremetal convert option"` - ConvertEsxiDefaultTemplate string `default:"Default template" help:"ESXI baremetal convert option"` + ConvertHypervisorDefaultTemplate string `help:"Kvm baremetal convert option"` + ConvertEsxiDefaultTemplate string `help:"ESXI baremetal convert option"` ConvertKubeletDockerVolumeSize string `default:"256g" help:"Docker volume size"` NfsDefaultImageCacheDir string `default:"image_cache"` diff --git a/pkg/compute/tasks/baremetal_convert_hypervisor_task.go b/pkg/compute/tasks/baremetal_convert_hypervisor_task.go index 3c2d3342d5..347006a083 100644 --- a/pkg/compute/tasks/baremetal_convert_hypervisor_task.go +++ b/pkg/compute/tasks/baremetal_convert_hypervisor_task.go @@ -91,7 +91,7 @@ func (self *BaremetalConvertHypervisorTask) OnGuestDeployCompleteFailed(ctx cont guest.SetDisableDelete(self.UserCred, false) self.SetStage("OnGuestDeleteComplete", nil) guest.StartDeleteGuestTask(ctx, self.UserCred, self.GetTaskId(), false, true) - logclient.AddActionLogWithStartable(self, baremetal, logclient.ACT_BM_CONVERT_HYPER, "convert deploy failed", self.UserCred, false) + logclient.AddActionLogWithStartable(self, baremetal, logclient.ACT_BM_CONVERT_HYPER, fmt.Sprintf("convert deploy failed: %s", body.String()), self.UserCred, false) } func (self *BaremetalConvertHypervisorTask) OnGuestDeleteComplete(ctx context.Context, baremetal *models.SHost, body jsonutils.JSONObject) {