From 75a4c042b2560039fd6e7ee68ae7d033105b501d Mon Sep 17 00:00:00 2001 From: ioito Date: Wed, 16 Feb 2022 16:23:38 +0800 Subject: [PATCH] fix(climc): server create with disk desc --- cmd/climc/shell/compute/servers.go | 45 +++++------- pkg/cloudcommon/cmdline/parser.go | 94 +++++++++++++++++++++---- pkg/mcclient/options/compute/servers.go | 23 +++++- 3 files changed, 116 insertions(+), 46 deletions(-) diff --git a/cmd/climc/shell/compute/servers.go b/cmd/climc/shell/compute/servers.go index a29dae200c..302578f18d 100644 --- a/cmd/climc/shell/compute/servers.go +++ b/cmd/climc/shell/compute/servers.go @@ -235,19 +235,6 @@ func init() { }, ) - R(&options.ServerCreateOptions{}, "server-check-create-data", "Check create server data", func(s *mcclient.ClientSession, opts *options.ServerCreateOptions) error { - params, err := opts.Params() - if err != nil { - return err - } - server, err := modules.Servers.PerformClassAction(s, "check-create-data", params.JSON(params)) - if err != nil { - return err - } - printObject(server) - 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 { @@ -265,24 +252,24 @@ func init() { return err } printList(modulebase.JSON2ListResult(result), listFields) + return nil + } + taskNotify := baseoptions.BoolV(opts.TaskNotify) + if taskNotify { + s.PrepareTask() + } + if count > 1 { + results := modules.Servers.BatchCreate(s, params.JSON(params), count) + printBatchResults(results, modules.Servers.GetColumns(s)) } else { - taskNotify := baseoptions.BoolV(opts.TaskNotify) - if taskNotify { - s.PrepareTask() - } - if count > 1 { - results := modules.Servers.BatchCreate(s, params.JSON(params), count) - printBatchResults(results, modules.Servers.GetColumns(s)) - } else { - server, err := modules.Servers.Create(s, params.JSON(params)) - if err != nil { - return err - } - printObject(server) - } - if taskNotify { - s.WaitTaskNotify() + server, err := modules.Servers.Create(s, params.JSON(params)) + if err != nil { + return err } + printObject(server) + } + if taskNotify { + s.WaitTaskNotify() } return nil }) diff --git a/pkg/cloudcommon/cmdline/parser.go b/pkg/cloudcommon/cmdline/parser.go index 0b471dbd2f..5307ba8ed7 100644 --- a/pkg/cloudcommon/cmdline/parser.go +++ b/pkg/cloudcommon/cmdline/parser.go @@ -15,13 +15,13 @@ package cmdline import ( - "errors" "fmt" "regexp" "strconv" "strings" "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" "yunion.io/x/pkg/util/fileutils" "yunion.io/x/pkg/util/netutils" "yunion.io/x/pkg/util/osprofile" @@ -33,7 +33,7 @@ import ( ) var ( - ErrorEmptyDesc = errors.New("Empty description") + ErrorEmptyDesc = errors.Errorf("Empty description") ) // ParseSchedtagConfig desc format: :: @@ -89,12 +89,22 @@ func ParseDiskConfig(diskStr string, idx int) (*compute.DiskConfig, error) { // default backend and medium type diskConfig.Backend = "" // STORAGE_LOCAL diskConfig.Medium = "" + diskConfig.SizeMb = -1 - parts := strings.Split(diskStr, ":") - for _, p := range parts { - if len(p) == 0 { - continue + oldPart, newPart := []string{}, []string{} + for _, d0 := range strings.Split(diskStr, ",") { + for _, d1 := range strings.Split(d0, ":") { + if len(d1) == 0 { + continue + } + if strings.Contains(d1, "=") { + newPart = append(newPart, d1) + continue + } + oldPart = append(oldPart, d1) } + } + for _, p := range oldPart { if regutils.MatchSize(p) { diskConfig.SizeMb, _ = fileutils.GetSizeMb(p, 'M', 1024) } else if utils.IsInStringArray(p, osprofile.FS_TYPES) { @@ -115,19 +125,73 @@ func ParseDiskConfig(diskStr string, idx int) (*compute.DiskConfig, error) { diskConfig.SizeMb = -1 } else if utils.IsInStringArray(p, compute.STORAGE_ALL_TYPES) { diskConfig.Backend = p - } 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 strings.HasPrefix(p, "disk=") { - diskConfig.DiskId = p[len("disk="):] - } else if strings.HasPrefix(p, "storage=") { - diskConfig.Storage = p[len("storage="):] } else if len(p) > 0 { diskConfig.ImageId = p } } - + for _, p := range newPart { + info := strings.Split(p, "=") + if len(info) != 2 { + return nil, errors.Errorf("invalid disk description %s", p) + } + var err error + desc, str := info[0], info[1] + switch desc { + case "size": + diskConfig.SizeMb, err = fileutils.GetSizeMb(str, 'M', 1024) + if err != nil { + return nil, errors.Errorf("invalid disk size %s", str) + } + case "fs": + if !utils.IsInStringArray(str, osprofile.FS_TYPES) { + return nil, errors.Errorf("invalid disk fs %s, allow choices: %s", str, osprofile.FS_TYPES) + } + diskConfig.Fs = str + case "format": + if !utils.IsInStringArray(str, osprofile.IMAGE_FORMAT_TYPES) { + return nil, errors.Errorf("invalid disk format %s, allow choices: %s", str, osprofile.IMAGE_FORMAT_TYPES) + } + diskConfig.Format = str + case "driver": + if !utils.IsInStringArray(str, osprofile.DISK_DRIVERS) { + return nil, errors.Errorf("invalid disk driver %s, allow choices: %s", str, osprofile.DISK_DRIVERS) + } + diskConfig.Driver = str + case "cache", "cache_mode": + if !utils.IsInStringArray(str, osprofile.DISK_CACHE_MODES) { + return nil, errors.Errorf("invalid disk cache mode %s, allow choices: %s", str, osprofile.DISK_CACHE_MODES) + } + diskConfig.Cache = str + case "medium": + if !utils.IsInStringArray(str, compute.DISK_TYPES) { + return nil, errors.Errorf("invalid disk medium type %s, allow choices: %s", str, compute.DISK_TYPES) + } + diskConfig.Medium = str + case "type", "disk_type": + diskTypes := []string{compute.DISK_TYPE_SYS, compute.DISK_TYPE_DATA} + if !utils.IsInStringArray(str, diskTypes) { + return nil, errors.Errorf("invalid disk type %s, allow choices: %s", str, diskTypes) + } + diskConfig.DiskType = str + case "mountpoint": + diskConfig.Mountpoint = str + case "storage_type", "backend": + if !utils.IsInStringArray(str, compute.STORAGE_ALL_TYPES) { + return nil, errors.Errorf("invalid disk storage type %s, allow choices: %s", str, compute.STORAGE_ALL_TYPES) + } + diskConfig.Backend = str + case "snapshot", "snapshot_id": + diskConfig.SnapshotId = str + case "disk", "disk_id": + diskConfig.DiskId = str + case "storage", "storage_id": + diskConfig.Storage = str + case "image", "image_id": + diskConfig.ImageId = str + default: + return nil, errors.Errorf("invalid disk description %s", p) + } + } return diskConfig, nil } diff --git a/pkg/mcclient/options/compute/servers.go b/pkg/mcclient/options/compute/servers.go index 9e4e8815d6..4aec414fb5 100644 --- a/pkg/mcclient/options/compute/servers.go +++ b/pkg/mcclient/options/compute/servers.go @@ -223,8 +223,27 @@ type ServerConfigs struct { Backup bool `help:"Create server with backup server"` AutoSwitchToBackupOnHostDown bool `help:"Auto switch to backup server on host down"` - Schedtag []string `help:"Schedule policy, key = aggregate name, value = require|exclude|prefer|avoid" metavar:""` - Disk []string `help:"Disk descriptions" nargs:"+"` + Schedtag []string `help:"Schedule policy, key = aggregate name, value = require|exclude|prefer|avoid" metavar:""` + Disk []string `help:" + Disk descriptions + size: 500M, 10G + fs: swap, ext2, ext3, ext4, xfs, ntfs, fat, hfsplus + format: qcow2, raw, docker, iso, vmdk, vmdkflatver1, vmdkflatver2, vmdkflat, vmdksparse, vmdksparsever1, vmdksparsever2, vmdksesparse, vhd + driver: virtio, ide, scsi, sata, pvscsi + cache_mod: writeback, none, writethrough + medium: rotate, ssd, hybrid + disk_type: sys, data + mountpoint: /, /opt + storage_type: local, rbd, nas, nfs + snapshot_id: use snapshot-list get snapshot id + disk_id: use disk-list get disk id + storage_id: use storage-list get storage id + image_id: use image-list get image id + for example: + --disk 'image_id=c2be02a4-7ff2-43e6-8a00-a489e04d2d6f,size=10G,driver=ide,storage_type=rbd' + --disk 'size=500M' + --disk 'snpahost_id=1ceb8c6d-6571-451d-8957-4bd3a871af85' + " nargs:"+"` DiskSchedtag []string `help:"Disk schedtag description, e.g. '0::'"` Net []string `help:"Network descriptions" metavar:"NETWORK"` NetSchedtag []string `help:"Network schedtag description, e.g. '0::'"`