Skip to content

Commit

Permalink
feat(region,host): add guest disk auto reset on shutdown support (#22199
Browse files Browse the repository at this point in the history
)
  • Loading branch information
wanyaoqi authored Feb 27, 2025
1 parent 1cd90f8 commit b2dba99
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 6 deletions.
5 changes: 5 additions & 0 deletions cmd/climc/shell/compute/disks.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ func init() {
AutoSnapshot string `help:"enable/disable auto snapshot of disk" choices:"enable|disable"`
DiskType string `help:"Disk type" choices:"data|volume|sys"`
IsSsd *bool `help:"mark disk as ssd" negative:"no-is-ssd"`
AutoReset *bool `help:"Enable auto reset disk after geust shutdown"`
}
R(&DiskUpdateOptions{}, "disk-update", "Update property of a virtual disk", func(s *mcclient.ClientSession, args *DiskUpdateOptions) error {
params := jsonutils.NewDict()
Expand Down Expand Up @@ -172,6 +173,10 @@ func init() {
params.Add(jsonutils.JSONFalse, "is_ssd")
}
}
if args.AutoReset != nil {
params.Add(jsonutils.NewBool(*args.AutoReset), "auto_reset")
}

if params.Size() == 0 {
return InvalidUpdateError()
}
Expand Down
4 changes: 4 additions & 0 deletions pkg/apis/compute/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ type DiskConfig struct {
// 文件系统特性
FsFeatures *DiskFsFeatures `json:"fs_features"`

// 关机后自动重置磁盘
// required: false
AutoReset bool `json:"auto_reset"`

// 磁盘存储格式
// enum: ["qcow2", "raw", "docker", "iso", "vmdk", "vmdkflatver1", "vmdkflatver2", "vmdkflat", "vmdksparse", "vmdksparsever1", "vmdksparsever2", "vmdksepsparse", "vhd"]
// requried: false
Expand Down
1 change: 1 addition & 0 deletions pkg/apis/compute/guest_disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ type GuestdiskJsonDesc struct {
Dev string `json:"dev"`
IsSSD bool `json:"is_ssd"`
NumQueues uint8 `json:"num_queues"`
AutoReset bool `json:"auto_reset"`

// esxi
ImageInfo struct {
Expand Down
2 changes: 2 additions & 0 deletions pkg/cloudcommon/cmdline/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ func ParseDiskConfig(diskStr string, idx int) (*compute.DiskConfig, error) {
diskConfig.Mountpoint = p
} else if p == "autoextend" {
diskConfig.SizeMb = -1
} else if p == "autoreset" {
diskConfig.AutoReset = true
} else if utils.IsInStringArray(p, compute.STORAGE_TYPES) {
diskConfig.Backend = p
} else if len(p) > 0 {
Expand Down
2 changes: 2 additions & 0 deletions pkg/compute/models/disks.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ type SDisk struct {
Preallocation string `width:"12" default:"off" charset:"ascii" nullable:"true" list:"user" update:"admin" json:"preallocation"`
// # is persistent
Nonpersistent bool `default:"false" list:"user" json:"nonpersistent"`
// auto reset disk after guest shutdown
AutoReset bool `default:"false" list:"user" update:"user" json:"auto_reset"`

// 是否标记为SSD磁盘
IsSsd bool `nullable:"false" default:"false" list:"user" update:"user" create:"optional"`
Expand Down
1 change: 1 addition & 0 deletions pkg/compute/models/guestdisks.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ func (self *SGuestdisk) GetDiskJsonDescAtHost(ctx context.Context, host *SHost,
desc.Index = self.Index
bootIndex := self.BootIndex
desc.BootIndex = &bootIndex
desc.AutoReset = disk.AutoReset

if len(disk.SnapshotId) > 0 {
needMerge := disk.GetMetadata(ctx, "merge_snapshot", nil)
Expand Down
1 change: 1 addition & 0 deletions pkg/compute/models/storages.go
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,7 @@ func (self *SStorage) createDisk(ctx context.Context, name string, diskConfig *a
disk.Iops = diskConfig.Iops
disk.Throughput = diskConfig.Throughput
disk.Preallocation = diskConfig.Preallocation
disk.AutoReset = diskConfig.AutoReset

if self.MediumType == api.DISK_TYPE_SSD {
disk.IsSsd = true
Expand Down
24 changes: 23 additions & 1 deletion pkg/hostman/guestman/qemu-kvm.go
Original file line number Diff line number Diff line change
Expand Up @@ -2174,8 +2174,30 @@ func (s *SKVMGuestInstance) pyLauncherPath() string {
return path.Join(s.HomeDir(), "startvm.py")
}

func (s *SKVMGuestInstance) getTmpDirPath() string {
hasResetDisk := false
for i := range s.Desc.Disks {
if s.Desc.Disks[i].AutoReset {
hasResetDisk = true
}
if s.Desc.Disks[i].AutoReset && utils.IsInStringArray(s.Desc.Disks[i].StorageType, api.FIEL_STORAGE) {
return filepath.Dir(s.Desc.Disks[i].Path)
}
}
if hasResetDisk {
return options.HostOptions.ResetDiskTmpDir
}
return ""
}

func (s *SKVMGuestInstance) scriptStart(ctx context.Context) error {
output, err := procutils.NewRemoteCommandAsFarAsPossible(s.manager.getPythonPath(), s.pyLauncherPath()).Output()
tmpDir := s.getTmpDirPath()
cmd := procutils.NewRemoteCommandAsFarAsPossible(s.manager.getPythonPath(), s.pyLauncherPath())
if tmpDir != "" {
envs := []string{fmt.Sprintf("TMPDIR=%s", tmpDir)}
cmd.SetEnv(envs)
}
output, err := cmd.Output()
if err != nil {
return fmt.Errorf("Start VM Failed %s %s", output, err)
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/hostman/guestman/qemu/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,9 @@ func getDiskDriveOption(drvOpt QemuOptions, disk *desc.SGuestDisk, isEncrypt boo
if isEncrypt {
opt += ",encrypt.format=luks,encrypt.key-secret=sec0"
}
if disk.AutoReset {
opt += ",snapshot=on"
}
// #opt += ",media=disk"
return drvOpt.Drive(opt)
}
Expand Down
7 changes: 4 additions & 3 deletions pkg/hostman/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,10 @@ type SHostOptions struct {

BinaryMemcleanPath string `help:"execute binary memclean path" default:"/opt/yunion/bin/memclean"`

MaxHotplugVCpuCount int `help:"maximal possible vCPU count that the platform kvm supports"`
PcieRootPortCount int `help:"pcie root port count" default:"2"`
EnableQemuDebugLog bool `help:"enable qemu debug logs" default:"false"`
MaxHotplugVCpuCount int `help:"maximal possible vCPU count that the platform kvm supports"`
PcieRootPortCount int `help:"pcie root port count" default:"2"`
EnableQemuDebugLog bool `help:"enable qemu debug logs" default:"false"`
ResetDiskTmpDir string `help:"auto reset disk after guest shutdown will write disk to tmpdir"`

// container related endpoint
// EnableContainerRuntime bool `help:"enable container runtime" default:"false"`
Expand Down
17 changes: 15 additions & 2 deletions pkg/util/procutils/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type Cmd interface {
Wait() error
Run() error
Kill() error
SetEnv([]string)
}

type Executor interface {
Expand All @@ -63,6 +64,10 @@ func (c *defaultCmd) Kill() error {
return c.Process.Kill()
}

func (c *defaultCmd) SetEnv(envs []string) {
c.Env = append(c.Env, envs...)
}

type defaultExecutor struct{}

func (e *defaultExecutor) Command(name string, args ...string) Cmd {
Expand All @@ -88,18 +93,26 @@ func (e *defaultExecutor) GetExitStatus(err error) (int, bool) {
}
}

type remoteCmd struct {
*client.Cmd
}

func (c *remoteCmd) SetEnv(envs []string) {
c.Env = append(c.Env, envs...)
}

type remoteExecutor struct{}

func (e *remoteExecutor) Command(name string, args ...string) Cmd {
cmd := client.Command(name, args...)
remoteCmdSetEnv(cmd)
return cmd
return &remoteCmd{cmd}
}

func (e *remoteExecutor) CommandContext(ctx context.Context, name string, args ...string) Cmd {
cmd := client.CommandContext(ctx, name, args...)
remoteCmdSetEnv(cmd)
return cmd
return &remoteCmd{cmd}
}

func (e *remoteExecutor) GetExitStatus(err error) (int, bool) {
Expand Down
4 changes: 4 additions & 0 deletions pkg/util/procutils/procutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ func (c *Command) Start() error {
return c.cmd.Start()
}

func (c *Command) SetEnv(envs []string) {
c.cmd.SetEnv(envs)
}

func (c *Command) Wait() error {
return c.cmd.Wait()
}
Expand Down

0 comments on commit b2dba99

Please sign in to comment.