diff --git a/cmd/climc/shell/compute/servers.go b/cmd/climc/shell/compute/servers.go index 2b45359a38..9eebc4daef 100644 --- a/cmd/climc/shell/compute/servers.go +++ b/cmd/climc/shell/compute/servers.go @@ -129,7 +129,7 @@ func init() { cmd.BatchPerform("stop-rescue", &options.ServerStartOptions{}) cmd.BatchPerform("sync-os-info", &options.ServerIdsOptions{}) cmd.BatchPerform("set-root-disk-matcher", &options.ServerSetRootDiskMatcher{}) - + cmd.Perform("disable-auto-merge-snapshot", &options.ServerDisableAutoMergeSnapshot{}) cmd.Get("vnc", new(options.ServerVncOptions)) cmd.Get("desc", new(options.ServerIdOptions)) cmd.Get("status", new(options.ServerIdOptions)) diff --git a/pkg/apis/compute/guest_const.go b/pkg/apis/compute/guest_const.go index 849f166780..117ca51c74 100644 --- a/pkg/apis/compute/guest_const.go +++ b/pkg/apis/compute/guest_const.go @@ -420,23 +420,24 @@ const ( VM_AZURE_DEFAULT_LOGIN_USER = compute.VM_AZURE_DEFAULT_LOGIN_USER VM_ZSTACK_DEFAULT_LOGIN_USER = compute.VM_ZSTACK_DEFAULT_LOGIN_USER - VM_METADATA_APP_TAGS = "app_tags" - VM_METADATA_CREATE_PARAMS = "create_params" - VM_METADATA_LOGIN_ACCOUNT = "login_account" - VM_METADATA_LOGIN_KEY = "login_key" - VM_METADATA_LAST_LOGIN_KEY = "last_login_key" - VM_METADATA_LOGIN_KEY_TIMESTAMP = "login_key_timestamp" - VM_METADATA_OS_ARCH = "os_arch" - VM_METADATA_OS_DISTRO = "os_distribution" - VM_METADATA_OS_NAME = "os_name" - VM_METADATA_OS_VERSION = "os_version" - VM_METADATA_CGROUP_CPUSET = "cgroup_cpuset" - VM_METADATA_ENABLE_MEMCLEAN = "enable_memclean" - VM_METADATA_HOTPLUG_CPU_MEM = "hotplug_cpu_mem" - VM_METADATA_HOT_REMOVE_NIC = "hot_remove_nic" - VM_METADATA_START_VMEM_MB = "start_vmem_mb" - VM_METADATA_START_VCPU_COUNT = "start_vcpu_count" - VM_METADATA_CPU_NUMA_PIN = "__cpu_numa_pin" + VM_METADATA_APP_TAGS = "app_tags" + VM_METADATA_CREATE_PARAMS = "create_params" + VM_METADATA_LOGIN_ACCOUNT = "login_account" + VM_METADATA_LOGIN_KEY = "login_key" + VM_METADATA_LAST_LOGIN_KEY = "last_login_key" + VM_METADATA_LOGIN_KEY_TIMESTAMP = "login_key_timestamp" + VM_METADATA_OS_ARCH = "os_arch" + VM_METADATA_OS_DISTRO = "os_distribution" + VM_METADATA_OS_NAME = "os_name" + VM_METADATA_OS_VERSION = "os_version" + VM_METADATA_CGROUP_CPUSET = "cgroup_cpuset" + VM_METADATA_ENABLE_MEMCLEAN = "enable_memclean" + VM_METADATA_HOTPLUG_CPU_MEM = "hotplug_cpu_mem" + VM_METADATA_HOT_REMOVE_NIC = "hot_remove_nic" + VM_METADATA_START_VMEM_MB = "start_vmem_mb" + VM_METADATA_START_VCPU_COUNT = "start_vcpu_count" + VM_METADATA_CPU_NUMA_PIN = "__cpu_numa_pin" + VM_METADATA_DISABLE_AUTO_MERGE_SNAPSHOT = "disable_auto_merge_snapshot" ) func Hypervisors2HostTypes(hypervisors []string) []string { diff --git a/pkg/cloudcommon/options/options.go b/pkg/cloudcommon/options/options.go index 6c2415e443..618ab85a07 100644 --- a/pkg/cloudcommon/options/options.go +++ b/pkg/cloudcommon/options/options.go @@ -158,6 +158,7 @@ type HostCommonOptions struct { EnableIsolatedDeviceWhitelist bool `help:"enable isolated device white list" default:"false"` ImageDeployDriver string `help:"Image deploy driver" default:"qemu-kvm" choices:"qemu-kvm|nbd|libguestfs"` DeployConcurrent int `help:"qemu-kvm deploy driver concurrent" default:"5"` + Qcow2Preallocation string `help:"Qcow2 image create preallocation" default:"metadata" choices:"disable|metadata|falloc|full"` } type DBOptions struct { diff --git a/pkg/compute/models/guest_actions.go b/pkg/compute/models/guest_actions.go index 60e5baef81..4f0599b81c 100644 --- a/pkg/compute/models/guest_actions.go +++ b/pkg/compute/models/guest_actions.go @@ -2230,8 +2230,7 @@ func (self *SGuest) attachIsolatedDevice(ctx context.Context, userCred mcclient. if len(dev.GuestId) > 0 { return fmt.Errorf("Isolated device already attached to another guest: %s", dev.GuestId) } - if dev.HostId != - self.HostId { + if dev.HostId != self.HostId { return fmt.Errorf("Isolated device and guest are not located in the same host") } _, err := db.Update(dev, func() error { @@ -6317,3 +6316,8 @@ func (self *SGuest) StartChangeBillingTypeTask(ctx context.Context, userCred mcc } return task.ScheduleRun(nil) } + +func (self *SGuest) PerformDisableAutoMergeSnapshots(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) { + disableAutoMergeSnapshot := jsonutils.QueryBoolean(data, "disable_auto_merge_snapshot", false) + return nil, self.SetMetadata(ctx, api.VM_METADATA_DISABLE_AUTO_MERGE_SNAPSHOT, disableAutoMergeSnapshot, userCred) +} diff --git a/pkg/hostman/guestman/qemu-kvm.go b/pkg/hostman/guestman/qemu-kvm.go index cdd0848a06..2ee3427780 100644 --- a/pkg/hostman/guestman/qemu-kvm.go +++ b/pkg/hostman/guestman/qemu-kvm.go @@ -3020,6 +3020,9 @@ func (s *SKVMGuestInstance) CreateFromDesc(desc *desc.SGuestDesc) error { } func (s *SKVMGuestInstance) GetNeedMergeBackingFileDiskIndexs() []int { + if s.isDisableAutoMergeSnapshots() { + return nil + } res := make([]int, 0) for _, disk := range s.Desc.Disks { if disk.MergeSnapshot { diff --git a/pkg/hostman/guestman/qemu-kvmhelper.go b/pkg/hostman/guestman/qemu-kvmhelper.go index ebfeaf02a5..d2c88a3924 100644 --- a/pkg/hostman/guestman/qemu-kvmhelper.go +++ b/pkg/hostman/guestman/qemu-kvmhelper.go @@ -230,7 +230,11 @@ func (s *SKVMGuestInstance) isWindows10() bool { } func (s *SKVMGuestInstance) isMemcleanEnabled() bool { - return s.Desc.Metadata["enable_memclean"] == "true" + return s.Desc.Metadata[api.VM_METADATA_ENABLE_MEMCLEAN] == "true" +} + +func (s *SKVMGuestInstance) isDisableAutoMergeSnapshots() bool { + return s.Desc.Metadata[api.VM_METADATA_DISABLE_AUTO_MERGE_SNAPSHOT] == "true" } func (s *SKVMGuestInstance) getMachine() string { diff --git a/pkg/hostman/host_services.go b/pkg/hostman/host_services.go index 7fc6e8927d..c46861c328 100644 --- a/pkg/hostman/host_services.go +++ b/pkg/hostman/host_services.go @@ -39,6 +39,7 @@ import ( "yunion.io/x/onecloud/pkg/hostman/storageman/diskhandlers" "yunion.io/x/onecloud/pkg/hostman/storageman/storagehandler" "yunion.io/x/onecloud/pkg/util/procutils" + "yunion.io/x/onecloud/pkg/util/qemuimg" "yunion.io/x/onecloud/pkg/util/sysutils" ) @@ -76,6 +77,10 @@ func (host *SHostService) RunService() { cronManager := cronman.InitCronJobManager(false, options.HostOptions.CronJobWorkerCount, options.HostOptions.TimeZone) hostutils.Init() + if err := qemuimg.SetPreallocation(options.HostOptions.Qcow2Preallocation); err != nil { + log.Fatalf("failed set qemuimg preallocation to %s: %s", options.HostOptions.Qcow2Preallocation, err) + } + hostInstance := hostinfo.Instance() if err := hostInstance.Init(); err != nil { log.Fatalf("Host instance init error: %v", err) diff --git a/pkg/mcclient/options/compute/servers.go b/pkg/mcclient/options/compute/servers.go index 4fa97c6abb..8c2b5de965 100644 --- a/pkg/mcclient/options/compute/servers.go +++ b/pkg/mcclient/options/compute/servers.go @@ -822,6 +822,16 @@ func (o *ServerModifySrcCheckOptions) Description() string { return "Modify src ip, mac check settings" } +type ServerDisableAutoMergeSnapshot struct { + ServerIdOptions + + DisableAutoMergeSnapshot bool `help:"Disable auto merge snapshots"` +} + +func (o *ServerDisableAutoMergeSnapshot) Params() (jsonutils.JSONObject, error) { + return options.StructToParams(o) +} + type ServerSendKeyOptions struct { ID string `help:"ID or Name of server" metavar:"Guest" json:"-"` KEYS string `help:"Special keys to send, eg. ctrl, alt, f12, shift, etc, separated by \"-\""` diff --git a/pkg/util/qemuimg/qemuimg.go b/pkg/util/qemuimg/qemuimg.go index d57214b5b4..93bb154f02 100644 --- a/pkg/util/qemuimg/qemuimg.go +++ b/pkg/util/qemuimg/qemuimg.go @@ -66,6 +66,19 @@ const ( const DefaultConvertCorutines = 8 +var preallocation = "metadata" + +func SetPreallocation(prealloc string) error { + if !utils.IsInStringArray(prealloc, []string{"", "disable", "metadata", "falloc", "full"}) { + return errors.Errorf("unsupported preallocation %s", prealloc) + } + if prealloc == "disable" { + prealloc = "" + } + preallocation = prealloc + return nil +} + type SQemuImage struct { Path string Password string @@ -735,8 +748,10 @@ func (img *SQemuImage) CreateQcow2(sizeMB int, compact bool, backPath string, pa } } else if !compact { sparseOpts := qcow2SparseOptions() - if sizeMB <= 1024*1024*4 { - options = append(options, "preallocation=metadata") + if preallocation != "" { + if sizeMB <= 1024*1024*4 { + options = append(options, fmt.Sprintf("preallocation=%s", preallocation)) + } } options = append(options, sparseOpts...) }