mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-19 10:46:58 +08:00
Merge pull request #12483 from ioito/automated-cherry-pick-of-#12481-upstream-release-3.7
Automated cherry pick of #12481: fix(host): same mountpoint rbd storage
This commit is contained in:
@@ -16,6 +16,8 @@ package compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type HoststorageDetails struct {
|
||||
@@ -58,3 +60,10 @@ type HoststorageListInput struct {
|
||||
|
||||
StorageFilterListInput
|
||||
}
|
||||
|
||||
type HostStorageCreateInput struct {
|
||||
apis.JoinResourceBaseCreateInput
|
||||
StorageId string `json:"storage_id"`
|
||||
HostId string `json:"host_id"`
|
||||
MountPoint string `json:"mount_point"`
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ func (self *SBaseHostDriver) ValidateResetDisk(ctx context.Context, userCred mcc
|
||||
return nil, httperrors.NewNotImplementedError("Not Implement ValidateResetDisk")
|
||||
}
|
||||
|
||||
func (self *SBaseHostDriver) ValidateAttachStorage(ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, storage *models.SStorage, data *jsonutils.JSONDict) error {
|
||||
return httperrors.NewNotImplementedError("Not Implement ValidateAttachStorage")
|
||||
func (self *SBaseHostDriver) ValidateAttachStorage(ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, storage *models.SStorage, input api.HostStorageCreateInput) (api.HostStorageCreateInput, error) {
|
||||
return input, httperrors.NewNotImplementedError("Not Implement ValidateAttachStorage")
|
||||
}
|
||||
|
||||
func (self *SBaseHostDriver) RequestAttachStorage(ctx context.Context, hoststorage *models.SHoststorage, host *models.SHost, storage *models.SStorage, task taskman.ITask) error {
|
||||
|
||||
@@ -59,48 +59,47 @@ func (self *SKVMHostDriver) GetHypervisor() string {
|
||||
return api.HYPERVISOR_KVM
|
||||
}
|
||||
|
||||
func (self *SKVMHostDriver) ValidateAttachStorage(ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, storage *models.SStorage, data *jsonutils.JSONDict) error {
|
||||
func (self *SKVMHostDriver) ValidateAttachStorage(ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, storage *models.SStorage, input api.HostStorageCreateInput) (api.HostStorageCreateInput, error) {
|
||||
if !utils.IsInStringArray(storage.StorageType, append([]string{api.STORAGE_LOCAL}, api.SHARED_STORAGE...)) {
|
||||
return httperrors.NewUnsupportOperationError("Unsupport attach %s storage for %s host", storage.StorageType, host.HostType)
|
||||
return input, httperrors.NewUnsupportOperationError("Unsupport attach %s storage for %s host", storage.StorageType, host.HostType)
|
||||
}
|
||||
if storage.StorageType == api.STORAGE_RBD {
|
||||
if host.HostStatus != api.HOST_ONLINE {
|
||||
return httperrors.NewInvalidStatusError("Attach rbd storage require host status is online")
|
||||
return input, httperrors.NewInvalidStatusError("Attach rbd storage require host status is online")
|
||||
}
|
||||
pool, _ := storage.StorageConf.GetString("pool")
|
||||
data.Set("mount_point", jsonutils.NewString(fmt.Sprintf("rbd:%s", pool)))
|
||||
input.MountPoint = fmt.Sprintf("rbd:%s", pool)
|
||||
} else if utils.IsInStringArray(storage.StorageType, api.SHARED_FILE_STORAGE) {
|
||||
mountPoint, err := data.GetString("mount_point")
|
||||
if err != nil {
|
||||
return httperrors.NewMissingParameterError("mount_point")
|
||||
if len(input.MountPoint) == 0 {
|
||||
return input, httperrors.NewMissingParameterError("mount_point")
|
||||
}
|
||||
count, err := models.HoststorageManager.Query().Equals("host_id", host.Id).Equals("mount_point", mountPoint).CountWithError()
|
||||
count, err := models.HoststorageManager.Query().Equals("host_id", host.Id).Equals("mount_point", input.MountPoint).CountWithError()
|
||||
if err != nil {
|
||||
return httperrors.NewInternalServerError("Query host storage error %s", err)
|
||||
return input, httperrors.NewInternalServerError("Query host storage error %s", err)
|
||||
}
|
||||
if count > 0 {
|
||||
return httperrors.NewBadRequestError("Host %s already have mount point %s with other storage", host.Name, mountPoint)
|
||||
return input, httperrors.NewBadRequestError("Host %s already have mount point %s with other storage", host.Name, input.MountPoint)
|
||||
}
|
||||
if host.HostStatus != api.HOST_ONLINE {
|
||||
return httperrors.NewInvalidStatusError("Attach nfs storage require host status is online")
|
||||
return input, httperrors.NewInvalidStatusError("Attach nfs storage require host status is online")
|
||||
}
|
||||
if storage.StorageType == api.STORAGE_GPFS {
|
||||
header := http.Header{}
|
||||
header.Set(mcclient.AUTH_TOKEN, userCred.GetTokenString())
|
||||
header.Set(mcclient.REGION_VERSION, "v2")
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("mount_point", jsonutils.NewString(mountPoint))
|
||||
params.Set("mount_point", jsonutils.NewString(input.MountPoint))
|
||||
urlStr := fmt.Sprintf("%s/storages/is-mount-point?%s", host.ManagerUri, params.QueryString())
|
||||
_, res, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "GET", urlStr, header, nil, false)
|
||||
if err != nil {
|
||||
return err
|
||||
return input, err
|
||||
}
|
||||
if !jsonutils.QueryBoolean(res, "is_mount_point", false) {
|
||||
return httperrors.NewBadRequestError("%s is not mount point %s", mountPoint, res)
|
||||
return input, httperrors.NewBadRequestError("%s is not mount point %s", input.MountPoint, res)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SKVMHostDriver) RequestAttachStorage(ctx context.Context, hoststorage *models.SHoststorage, host *models.SHost, storage *models.SStorage, task taskman.ITask) error {
|
||||
@@ -141,6 +140,7 @@ func (self *SKVMHostDriver) RequestDetachStorage(ctx context.Context, host *mode
|
||||
mountPoint, _ := task.GetParams().GetString("mount_point")
|
||||
body.Set("mount_point", jsonutils.NewString(mountPoint))
|
||||
body.Set("name", jsonutils.NewString(storage.Name))
|
||||
body.Set("storage_id", jsonutils.NewString(storage.Id))
|
||||
_, resp, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, "POST", url, headers, body, false)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ type IHostDriver interface {
|
||||
IsReachStoragecacheCapacityLimit(host *SHost, cachedImages []SCachedimage) bool
|
||||
GetStoragecacheQuota(host *SHost) int
|
||||
|
||||
ValidateAttachStorage(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, storage *SStorage, data *jsonutils.JSONDict) error
|
||||
ValidateAttachStorage(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, storage *SStorage, input api.HostStorageCreateInput) (api.HostStorageCreateInput, error)
|
||||
RequestAttachStorage(ctx context.Context, hoststorage *SHoststorage, host *SHost, storage *SStorage, task taskman.ITask) error
|
||||
RequestDetachStorage(ctx context.Context, host *SHost, storage *SStorage, task taskman.ITask) error
|
||||
RequestSyncOnHost(ctx context.Context, host *SHost, task taskman.ITask) error
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
@@ -146,42 +147,28 @@ func (self *SHoststorage) GetStorage() *SStorage {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SHoststorageManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
storageId, _ := data.GetString("storage_id")
|
||||
if len(storageId) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("storage_id")
|
||||
}
|
||||
storageTmp, _ := StorageManager.FetchById(storageId)
|
||||
if storageTmp == nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("failed to find storage %s to attach host", storageId)
|
||||
}
|
||||
storage := storageTmp.(*SStorage)
|
||||
|
||||
hostId, _ := data.GetString("host_id")
|
||||
if len(hostId) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("host_id")
|
||||
}
|
||||
hostTmp, _ := HostManager.FetchById(hostId)
|
||||
if hostTmp == nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("failed to find host %s to attach storage", hostId)
|
||||
}
|
||||
host := hostTmp.(*SHost)
|
||||
|
||||
if err := host.GetHostDriver().ValidateAttachStorage(ctx, userCred, host, storage, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
input := apis.JoinResourceBaseCreateInput{}
|
||||
err := data.Unmarshal(&input)
|
||||
func (manager *SHoststorageManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.HostStorageCreateInput) (api.HostStorageCreateInput, error) {
|
||||
storageObj, err := validators.ValidateModel(userCred, StorageManager, &input.StorageId)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("unmarshal JoinResourceBaseCreateInput fail %s", err)
|
||||
return input, err
|
||||
}
|
||||
input, err = manager.SJointResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input)
|
||||
storage := storageObj.(*SStorage)
|
||||
hostObj, err := validators.ValidateModel(userCred, HostManager, &input.HostId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return input, err
|
||||
}
|
||||
data.Update(jsonutils.Marshal(input))
|
||||
return data, nil
|
||||
host := hostObj.(*SHost)
|
||||
|
||||
input, err = host.GetHostDriver().ValidateAttachStorage(ctx, userCred, host, storage, input)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
|
||||
input.JoinResourceBaseCreateInput, err = manager.SJointResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.JoinResourceBaseCreateInput)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SHoststorage) syncLocalStorageShare(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
|
||||
@@ -201,6 +201,19 @@ func (s *SStorageManager) GetStorageDisk(storageId, diskId string) IDisk {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SStorageManager) GetStoragesByPath(sPath string) ([]IStorage, error) {
|
||||
ret := []IStorage{}
|
||||
for i := range s.Storages {
|
||||
if s.Storages[i].GetPath() == sPath {
|
||||
ret = append(ret, s.Storages[i])
|
||||
}
|
||||
}
|
||||
if len(ret) == 0 {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, sPath)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (s *SStorageManager) GetStorageByPath(sPath string) (IStorage, error) {
|
||||
for _, storage := range s.Storages {
|
||||
if storage.GetPath() == sPath {
|
||||
@@ -218,11 +231,20 @@ func (s *SStorageManager) GetDiskByPath(diskPath string) (IDisk, error) {
|
||||
if pos > 0 {
|
||||
diskId = diskId[:pos]
|
||||
}
|
||||
storage, err := s.GetStorageByPath(sPath)
|
||||
storages, err := s.GetStoragesByPath(sPath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetStorageByPath")
|
||||
return nil, errors.Wrapf(err, "GetStoragesByPath")
|
||||
}
|
||||
return storage.GetDiskById(diskId)
|
||||
for i := range storages {
|
||||
disk, err := storages[i].GetDiskById(diskId)
|
||||
if err != nil && errors.Cause(err) != cloudprovider.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
if err == nil {
|
||||
return disk, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, diskId)
|
||||
}
|
||||
|
||||
func (s *SStorageManager) GetTotalCapacity() int {
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
@@ -128,22 +127,25 @@ func storageAttach(ctx context.Context, body jsonutils.JSONObject) (interface{},
|
||||
}
|
||||
|
||||
func storageDetach(ctx context.Context, body jsonutils.JSONObject) (interface{}, error) {
|
||||
mountPoint, err := body.GetString("mount_point")
|
||||
info := struct {
|
||||
MountPoint string
|
||||
StorageId string
|
||||
Name string
|
||||
}{}
|
||||
err := body.Unmarshal(&info)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("mount_point")
|
||||
return nil, errors.Wrapf(err, "body.Unmarshal")
|
||||
}
|
||||
storage, err := storageman.GetManager().GetStorageByPath(mountPoint)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
return nil, nil
|
||||
if len(info.StorageId) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("storage_id")
|
||||
}
|
||||
storage := storageman.GetManager().GetStorage(info.StorageId)
|
||||
if storage != nil {
|
||||
if err := storage.Detach(); err != nil {
|
||||
log.Errorf("detach storage %s failed: %s", storage.GetPath(), err)
|
||||
}
|
||||
return nil, errors.Wrapf(err, "GetStorageByPath(%s)", mountPoint)
|
||||
storageman.GetManager().Remove(storage)
|
||||
}
|
||||
|
||||
if err := storage.Detach(); err != nil {
|
||||
log.Errorf("detach storage %s failed: %s", storage.GetPath(), err)
|
||||
}
|
||||
storageman.GetManager().Remove(storage)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user