mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-31 01:35:56 +08:00
feat(region,host,host-deployer): container disk support resize (#21398)
This commit is contained in:
@@ -635,12 +635,15 @@ func (self *SKVMGuestDriver) GetDeployStatus() ([]string, error) {
|
||||
}
|
||||
|
||||
func (self *SKVMGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *models.SDisk, storage *models.SStorage) error {
|
||||
if guest.GetDiskIndex(disk.Id) <= 0 && guest.Status == api.VM_RUNNING {
|
||||
return fmt.Errorf("Cann't online resize root disk")
|
||||
}
|
||||
if guest.Status == api.VM_RUNNING && storage.StorageType == api.STORAGE_SLVM {
|
||||
return fmt.Errorf("shared lvm storage cann't online resize")
|
||||
if guest.Hypervisor == api.HYPERVISOR_KVM {
|
||||
if guest.GetDiskIndex(disk.Id) <= 0 && guest.Status == api.VM_RUNNING {
|
||||
return fmt.Errorf("Cann't online resize root disk")
|
||||
}
|
||||
if guest.Status == api.VM_RUNNING && storage.StorageType == api.STORAGE_SLVM {
|
||||
return fmt.Errorf("shared lvm storage cann't online resize")
|
||||
}
|
||||
}
|
||||
|
||||
if !utils.IsInStringArray(guest.Status, []string{api.VM_READY, api.VM_RUNNING}) {
|
||||
return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ func GetDevSector512Count(dev string) int {
|
||||
return size
|
||||
}
|
||||
|
||||
func ResizeDiskFs(diskPath string, sizeMb int) error {
|
||||
func ResizeDiskFs(diskPath string, sizeMb int, mounted bool) error {
|
||||
var cmds = []string{"parted", "-a", "none", "-s", diskPath, "--", "unit", "s", "print"}
|
||||
lines, err := procutils.NewCommand(cmds[0], cmds[1:]...).Output()
|
||||
if err != nil {
|
||||
@@ -205,7 +205,7 @@ func ResizeDiskFs(diskPath string, sizeMb int) error {
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "growpart failed %s", output)
|
||||
}
|
||||
err, _ = ResizePartitionFs(part[7], part[6], false)
|
||||
err, _ = ResizePartitionFs(part[7], part[6], false, mounted)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "resize fs %s", part[6])
|
||||
}
|
||||
@@ -225,7 +225,7 @@ func IsSupportResizeFs(fs string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func ResizePartitionFs(fpath, fs string, raiseError bool) (error, bool) {
|
||||
func ResizePartitionFs(fpath, fs string, raiseError, mounted bool) (error, bool) {
|
||||
if len(fs) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
@@ -240,13 +240,16 @@ func ResizePartitionFs(fpath, fs string, raiseError bool) (error, bool) {
|
||||
cmds = [][]string{{"mkswap", fpath}}
|
||||
}
|
||||
} else if strings.HasPrefix(fs, "ext") {
|
||||
if !FsckExtFs(fpath) {
|
||||
if raiseError {
|
||||
return fmt.Errorf("Failed to fsck ext fs %s", fpath), false
|
||||
} else {
|
||||
return nil, false
|
||||
if !mounted {
|
||||
if !FsckExtFs(fpath) {
|
||||
if raiseError {
|
||||
return fmt.Errorf("Failed to fsck ext fs %s", fpath), false
|
||||
} else {
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cmds = [][]string{{"resize2fs", fpath}}
|
||||
} else if fs == "xfs" {
|
||||
var tmpPoint = fmt.Sprintf("/tmp/%s", strings.Replace(fpath, "/", "_", -1))
|
||||
@@ -297,23 +300,22 @@ func ResizePartitionFs(fpath, fs string, raiseError bool) (error, bool) {
|
||||
func FsckExtFs(fpath string) bool {
|
||||
log.Debugf("Exec command: %v", []string{"e2fsck", "-f", "-p", fpath})
|
||||
cmd := procutils.NewCommand("e2fsck", "-f", "-p", fpath)
|
||||
if err := cmd.Start(); err != nil {
|
||||
log.Errorf("e2fsck start failed: %s", err)
|
||||
return false
|
||||
} else {
|
||||
err = cmd.Wait()
|
||||
if err != nil {
|
||||
if status, ok := cmd.GetExitStatus(err); ok {
|
||||
if status < 4 {
|
||||
return true
|
||||
}
|
||||
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
log.Errorf("e2fsck failed %s: %s", err, out)
|
||||
if status, ok := cmd.GetExitStatus(err); ok {
|
||||
log.Errorf("e2fsck exit status %d", status)
|
||||
if status < 4 {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
log.Errorln(err)
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// https://bugs.launchpad.net/ubuntu/+source/xfsprogs/+bug/1718244
|
||||
|
||||
@@ -214,7 +214,7 @@ func (d *SLibguestfsDriver) ResizePartition() error {
|
||||
// do not try to resize LVM partition
|
||||
return nil
|
||||
}
|
||||
return fsutils.ResizeDiskFs(d.nbddev, 0)
|
||||
return fsutils.ResizeDiskFs(d.nbddev, 0, false)
|
||||
}
|
||||
|
||||
func (d *SLibguestfsDriver) FormatPartition(fs, uuid string) error {
|
||||
|
||||
@@ -248,7 +248,7 @@ func (d *NBDDriver) ResizePartition() error {
|
||||
// do not resize LVM partition
|
||||
return nil
|
||||
}
|
||||
return fsutils.ResizeDiskFs(d.nbdDev, 0)
|
||||
return fsutils.ResizeDiskFs(d.nbdDev, 0, false)
|
||||
}
|
||||
|
||||
func (d *NBDDriver) Zerofree() {
|
||||
|
||||
@@ -93,7 +93,7 @@ func (d *LocalDiskDriver) ResizePartition() error {
|
||||
// do not resize LVM partition
|
||||
return nil
|
||||
}
|
||||
return fsutils.ResizeDiskFs("/dev/sda", 0)
|
||||
return fsutils.ResizeDiskFs("/dev/sda", 0, false)
|
||||
}
|
||||
|
||||
func (d *LocalDiskDriver) FormatPartition(fs, uuid string) error {
|
||||
|
||||
@@ -1443,12 +1443,12 @@ func (m *SGuestManager) Resume(ctx context.Context, sid string, isLiveMigrate bo
|
||||
}
|
||||
|
||||
func (m *SGuestManager) OnlineResizeDisk(ctx context.Context, sid string, disk storageman.IDisk, sizeMb int64) (jsonutils.JSONObject, error) {
|
||||
guest, ok := m.GetKVMServer(sid)
|
||||
guest, ok := m.GetServer(sid)
|
||||
if !ok {
|
||||
return nil, httperrors.NewNotFoundError("guest %s not found", sid)
|
||||
}
|
||||
if guest.IsRunning() {
|
||||
guest.onlineResizeDisk(ctx, disk, sizeMb)
|
||||
guest.OnlineResizeDisk(ctx, disk, sizeMb)
|
||||
return nil, nil
|
||||
} else {
|
||||
return nil, httperrors.NewInvalidStatusError("guest is not runnign")
|
||||
|
||||
@@ -2190,6 +2190,42 @@ func (s *sPodGuestInstance) DeleteSnapshot(ctx context.Context, params *SDeleteD
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (s *sPodGuestInstance) doOnlineResizeDisk(ctx context.Context, disk storageman.IDisk, sizeMB int64) {
|
||||
drv, err := disk.GetContainerStorageDriver()
|
||||
if err != nil {
|
||||
hostutils.TaskFailed(ctx, fmt.Sprintf("get disk storage driver %s", err))
|
||||
return
|
||||
}
|
||||
partDev, found, err := drv.CheckConnect(disk.GetPath())
|
||||
if err != nil {
|
||||
hostutils.TaskFailed(ctx, fmt.Sprintf("disk check connect %s", err))
|
||||
return
|
||||
}
|
||||
if !found {
|
||||
hostutils.TaskFailed(ctx, fmt.Sprintf("online resize but loop device not connected"))
|
||||
return
|
||||
}
|
||||
|
||||
if err := disk.PreResize(ctx, sizeMB); err != nil {
|
||||
hostutils.TaskFailed(ctx, fmt.Sprintf("PreResize failed %s", err))
|
||||
return
|
||||
}
|
||||
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("size", jsonutils.NewInt(sizeMB))
|
||||
params.Set("loop_part_dev", jsonutils.NewString(partDev))
|
||||
res, err := disk.Resize(ctx, params)
|
||||
if err != nil {
|
||||
hostutils.TaskFailed(ctx, fmt.Sprintf("PreResize failed %s", err))
|
||||
return
|
||||
}
|
||||
hostutils.TaskComplete(ctx, res)
|
||||
}
|
||||
|
||||
func (s *sPodGuestInstance) OnlineResizeDisk(ctx context.Context, disk storageman.IDisk, sizeMB int64) {
|
||||
go s.doOnlineResizeDisk(ctx, disk, sizeMB)
|
||||
}
|
||||
|
||||
func (s *sPodGuestInstance) ContainerExecSync(ctx context.Context, userCred mcclient.TokenCredential, ctrId string, input *computeapi.ContainerExecSyncInput) (jsonutils.JSONObject, error) {
|
||||
ctrCriId, err := s.getContainerCRIId(ctrId)
|
||||
if err != nil {
|
||||
|
||||
@@ -3278,7 +3278,7 @@ func (s *SKVMGuestInstance) prepareNicsForVolatileGuestResume() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SKVMGuestInstance) onlineResizeDisk(ctx context.Context, disk storageman.IDisk, sizeMB int64) {
|
||||
func (s *SKVMGuestInstance) OnlineResizeDisk(ctx context.Context, disk storageman.IDisk, sizeMB int64) {
|
||||
task := NewGuestOnlineResizeDiskTask(ctx, s, disk, sizeMB)
|
||||
task.Start()
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestman/desc"
|
||||
deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/cgrouputils/cpuset"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
@@ -70,6 +71,7 @@ type GuestRuntimeInstance interface {
|
||||
SyncConfig(ctx context.Context, guestDesc *desc.SGuestDesc, fwOnly bool) (jsonutils.JSONObject, error)
|
||||
DoSnapshot(ctx context.Context, params *SDiskSnapshot) (jsonutils.JSONObject, error)
|
||||
DeleteSnapshot(ctx context.Context, params *SDeleteDiskSnapshot) (jsonutils.JSONObject, error)
|
||||
OnlineResizeDisk(ctx context.Context, disk storageman.IDisk, sizeMB int64)
|
||||
}
|
||||
|
||||
type sBaseGuestInstance struct {
|
||||
|
||||
@@ -129,6 +129,15 @@ func (*DeployerServer) ResizeFs(ctx context.Context, req *deployapi.ResizeFsPara
|
||||
}
|
||||
}()
|
||||
log.Infof("********* Resize fs on %#v", apiDiskInfo(req.DiskInfo))
|
||||
|
||||
if strings.HasPrefix(req.DiskInfo.Path, "/dev/loop") {
|
||||
// HACK: container loop device, do resize locally
|
||||
if err := fsutils.ResizeDiskFs(req.DiskInfo.Path, 0, true); err != nil {
|
||||
return new(deployapi.Empty), errors.Wrap(err, "fsutils.ResizeDiskFs")
|
||||
}
|
||||
return new(deployapi.Empty), nil
|
||||
}
|
||||
|
||||
disk, err := diskutils.GetIDisk(diskutils.DiskParams{
|
||||
Hypervisor: req.Hypervisor,
|
||||
DiskInfo: apiDiskInfo(req.GetDiskInfo()),
|
||||
|
||||
@@ -41,6 +41,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/auth"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
"yunion.io/x/onecloud/pkg/util/fuseutils"
|
||||
"yunion.io/x/onecloud/pkg/util/losetup"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
"yunion.io/x/onecloud/pkg/util/qemuimg"
|
||||
"yunion.io/x/onecloud/pkg/util/seclib2"
|
||||
@@ -155,6 +156,15 @@ func (d *SLocalDisk) OnRebuildRoot(ctx context.Context, params api.DiskAllocateI
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) ResizeLoopDevice(partDev string) (string, error) {
|
||||
loopDevice := strings.TrimSuffix(partDev, "p1")
|
||||
err := losetup.ResizeLoopDevice(loopDevice)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "ResizeLoopDevice")
|
||||
}
|
||||
return loopDevice, nil
|
||||
}
|
||||
|
||||
func (d *SLocalDisk) Resize(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
|
||||
diskInfo, ok := params.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
@@ -170,6 +180,7 @@ func (d *SLocalDisk) Resize(ctx context.Context, params interface{}) (jsonutils.
|
||||
resizeFsInfo := &deployapi.DiskInfo{
|
||||
Path: d.GetPath(),
|
||||
}
|
||||
|
||||
if diskInfo.Contains("encrypt_info") {
|
||||
var encryptInfo apis.SEncryptInfo
|
||||
err := diskInfo.Unmarshal(&encryptInfo, "encrypt_info")
|
||||
@@ -187,10 +198,20 @@ func (d *SLocalDisk) Resize(ctx context.Context, params interface{}) (jsonutils.
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if options.HostOptions.EnableFallocateDisk {
|
||||
err := d.fallocate()
|
||||
|
||||
if diskInfo.Contains("loop_part_dev") {
|
||||
partDev, _ := diskInfo.GetString("loop_part_dev")
|
||||
loopDev, err := d.ResizeLoopDevice(partDev)
|
||||
if err != nil {
|
||||
log.Errorf("fallocate fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
resizeFsInfo.Path = loopDev
|
||||
} else {
|
||||
if options.HostOptions.EnableFallocateDisk {
|
||||
err := d.fallocate()
|
||||
if err != nil {
|
||||
log.Errorf("fallocate fail %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -207,3 +207,8 @@ func DetachDeviceByFile(filePath string) error {
|
||||
_, err = NewLosetupCommand().AddArgs("-d", dev.Name).Run()
|
||||
return err
|
||||
}
|
||||
|
||||
func ResizeLoopDevice(loopDev string) error {
|
||||
_, err := NewLosetupCommand().AddArgs("-c", loopDev).Run()
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user