Files
cloudpods/pkg/hostman/storageman/disk_rbd.go
Jian Qiu 772f444621 region/host: fix reset ceph root disk after rebuild root (#13798)
Ceph storage disk rebuild root will rename origin disk to backing
disk, so we need use backing disk reset snapshot.

Signed-off-by: wanyaoqi <wanyaoqi1995@163.com>

Co-authored-by: wanyaoqi <wanyaoqi1995@163.com>
2022-03-27 11:34:55 +08:00

292 lines
9.2 KiB
Go

// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package storageman
import (
"context"
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/appctx"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/hostman/hostutils"
)
type SRBDDisk struct {
SBaseDisk
}
func NewRBDDisk(storage IStorage, id string) *SRBDDisk {
var ret = new(SRBDDisk)
ret.SBaseDisk = *NewBaseDisk(storage, id)
return ret
}
func (d *SRBDDisk) GetType() string {
return api.STORAGE_RBD
}
func (d *SRBDDisk) Probe() error {
storage := d.Storage.(*SRbdStorage)
exist, err := storage.IsImageExist(d.Id)
if err != nil {
return errors.Wrapf(err, "IsImageExist")
}
if !exist {
return cloudprovider.ErrNotFound
}
return nil
}
func (d *SRBDDisk) getPath() string {
return d.Storage.(*SRbdStorage).getDiskPath(d.Id)
}
func (d *SRBDDisk) GetPath() string {
storage := d.Storage.(*SRbdStorage)
return fmt.Sprintf("%s%s", d.getPath(), storage.getStorageConfString())
}
func (d *SRBDDisk) GetSnapshotDir() string {
return ""
}
func (d *SRBDDisk) GetDiskDesc() jsonutils.JSONObject {
storage := d.Storage.(*SRbdStorage)
storageConf := d.Storage.GetStorageConf()
pool, _ := storageConf.GetString("pool")
sizeMb, _ := storage.getImageSizeMb(pool, d.Id)
desc := map[string]interface{}{
"disk_id": d.Id,
"disk_format": "raw",
"disk_path": d.getPath(),
"disk_size": sizeMb,
}
return jsonutils.Marshal(desc)
}
func (d *SRBDDisk) GetDiskSetupScripts(idx int) string {
return fmt.Sprintf("DISK_%d='%s'\n", idx, d.GetPath())
}
func (d *SRBDDisk) DeleteAllSnapshot(skipRecycle bool) error {
return fmt.Errorf("Not Impl")
}
func (d *SRBDDisk) Delete(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
p := params.(api.DiskDeleteInput)
storage := d.Storage.(*SRbdStorage)
storageConf := d.Storage.GetStorageConf()
pool, _ := storageConf.GetString("pool")
return nil, storage.deleteImage(pool, d.Id, p.SkipRecycle != nil && *p.SkipRecycle)
}
func (d *SRBDDisk) OnRebuildRoot(ctx context.Context, params api.DiskAllocateInput) error {
if len(params.BackingDiskId) == 0 {
_, err := d.Delete(ctx, api.DiskDeleteInput{})
return err
}
storage := d.Storage.(*SRbdStorage)
storageConf := d.Storage.GetStorageConf()
pool, _ := storageConf.GetString("pool")
return storage.renameImage(pool, d.Id, params.BackingDiskId)
}
func (d *SRBDDisk) Resize(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
diskInfo, ok := params.(*jsonutils.JSONDict)
if !ok {
return nil, hostutils.ParamsError
}
storage := d.Storage.(*SRbdStorage)
storageConf := d.Storage.GetStorageConf()
pool, _ := storageConf.GetString("pool")
sizeMb, _ := diskInfo.Int("size")
if err := storage.resizeImage(pool, d.Id, uint64(sizeMb)); err != nil {
return nil, err
}
if err := d.ResizeFs(d.GetPath()); err != nil {
return nil, errors.Wrapf(err, "resize fs %s", d.GetPath())
}
return d.GetDiskDesc(), nil
}
func (d *SRBDDisk) PrepareSaveToGlance(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
if err := d.Probe(); err != nil {
return nil, err
}
imageName := fmt.Sprintf("image_cache_%s_%s", d.Id, appctx.AppContextTaskId(ctx))
imageCache := storageManager.GetStoragecacheById(d.Storage.GetStoragecacheId())
if imageCache == nil {
return nil, fmt.Errorf("failed to find image cache for prepare save to glance")
}
storage := d.Storage.(*SRbdStorage)
pool, _ := storage.GetStorageConf().GetString("pool")
if err := storage.cloneImage(ctx, pool, d.Id, imageCache.GetPath(), imageName); err != nil {
log.Errorf("clone image %s from pool %s to %s/%s error: %v", d.Id, pool, imageCache.GetPath(), imageName, err)
return nil, err
}
return jsonutils.Marshal(map[string]string{"backup": imageName}), nil
}
func (d *SRBDDisk) CleanupSnapshots(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
storage := d.Storage.(*SRbdStorage)
pool, _ := storage.StorageConf.GetString("pool")
return nil, storage.deleteSnapshot(pool, d.Id, "")
}
func (d *SRBDDisk) PrepareMigrate(liveMigrate bool) (string, error) {
return "", fmt.Errorf("Not support")
}
func (d *SRBDDisk) CreateFromTemplate(ctx context.Context, imageId string, format string, size int64) (jsonutils.JSONObject, error) {
ret, err := d.createFromTemplate(ctx, imageId, format)
if err != nil {
return nil, err
}
retSize, _ := ret.Int("disk_size")
log.Infof("REQSIZE: %d, RETSIZE: %d", size, retSize)
if size > retSize {
params := jsonutils.NewDict()
params.Set("size", jsonutils.NewInt(size))
return d.Resize(ctx, params)
}
return ret, nil
}
func (d *SRBDDisk) createFromTemplate(ctx context.Context, imageId, format string) (jsonutils.JSONObject, error) {
var imageCacheManager = storageManager.GetStoragecacheById(d.Storage.GetStoragecacheId())
if imageCacheManager == nil {
return nil, fmt.Errorf("failed to find image cache manger for storage %s", d.Storage.GetStorageName())
}
input := api.CacheImageInput{
ImageId: imageId,
Zone: d.GetZoneName(),
}
imageCache, err := imageCacheManager.AcquireImage(ctx, input, nil)
if err != nil {
return nil, errors.Wrapf(err, "AcquireImage")
}
defer imageCacheManager.ReleaseImage(ctx, imageId)
storage := d.Storage.(*SRbdStorage)
destPool, _ := storage.StorageConf.GetString("pool")
storage.deleteImage(destPool, d.Id, false) //重装系统时,需要删除以前的系统盘
err = storage.cloneImage(ctx, imageCacheManager.GetPath(), imageCache.GetName(), destPool, d.Id)
if err != nil {
return nil, errors.Wrapf(err, "cloneImage(%s)", imageCache.GetName())
}
return d.GetDiskDesc(), nil
}
func (d *SRBDDisk) CreateFromImageFuse(ctx context.Context, url string, size int64) error {
return fmt.Errorf("Not support")
}
func (d *SRBDDisk) CreateRaw(ctx context.Context, sizeMb int, diskFromat string, fsFormat string, encryption bool, diskId string, back string) (jsonutils.JSONObject, error) {
storage := d.Storage.(*SRbdStorage)
pool, _ := storage.StorageConf.GetString("pool")
if err := storage.createImage(pool, diskId, uint64(sizeMb)); err != nil {
return nil, err
}
if utils.IsInStringArray(fsFormat, []string{"swap", "ext2", "ext3", "ext4", "xfs"}) {
d.FormatFs(fsFormat, diskId, d.GetPath())
}
return d.GetDiskDesc(), nil
}
func (d *SRBDDisk) PostCreateFromImageFuse() {
log.Errorf("Not support PostCreateFromImageFuse")
}
func (d *SRBDDisk) DiskBackup(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
diskBackup := params.(*SDiskBakcup)
storage := d.Storage.(*SRbdStorage)
pool, _ := storage.StorageConf.GetString("pool")
sizeMb, err := storage.createBackup(pool, d.Id, diskBackup.SnapshotId, diskBackup.BackupId, diskBackup.BackupStorageId, diskBackup.BackupStorageAccessInfo)
if err != nil {
return nil, err
}
data := jsonutils.NewDict()
data.Set("size_mb", jsonutils.NewInt(int64(sizeMb)))
return data, nil
}
func (d *SRBDDisk) CreateSnapshot(snapshotId string) error {
storage := d.Storage.(*SRbdStorage)
pool, _ := storage.StorageConf.GetString("pool")
return storage.createSnapshot(pool, d.Id, snapshotId)
}
func (d *SRBDDisk) DeleteSnapshot(snapshotId, convertSnapshot string, pendingDelete bool) error {
storage := d.Storage.(*SRbdStorage)
pool, _ := storage.StorageConf.GetString("pool")
return storage.deleteSnapshot(pool, d.Id, snapshotId)
}
func (d *SRBDDisk) DiskSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
snapshotId, ok := params.(string)
if !ok {
return nil, hostutils.ParamsError
}
return nil, d.CreateSnapshot(snapshotId)
}
func (d *SRBDDisk) DiskDeleteSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
snapshotId, ok := params.(string)
if !ok {
return nil, hostutils.ParamsError
}
err := d.DeleteSnapshot(snapshotId, "", false)
if err != nil {
return nil, err
} else {
res := jsonutils.NewDict()
res.Set("deleted", jsonutils.JSONTrue)
return res, nil
}
}
func (d *SRBDDisk) ResetFromSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
resetParams, ok := params.(*SDiskReset)
if !ok {
return nil, hostutils.ParamsError
}
diskId := resetParams.BackingDiskId
if len(diskId) == 0 {
diskId = d.GetId()
}
storage := d.Storage.(*SRbdStorage)
pool, _ := storage.StorageConf.GetString("pool")
return nil, storage.resetDisk(pool, diskId, resetParams.SnapshotId)
}
func (d *SRBDDisk) CreateFromRbdSnapshot(ctx context.Context, snapshot, srcDiskId, srcPool string) error {
storage := d.Storage.(*SRbdStorage)
pool, _ := storage.StorageConf.GetString("pool")
return storage.cloneFromSnapshot(srcDiskId, srcPool, snapshot, d.GetId(), pool)
}