fix: 避免创建vmware磁盘快照

This commit is contained in:
Qu Xuan
2019-11-01 15:40:43 +08:00
parent e9156bea4a
commit c5e1b75caa
14 changed files with 68 additions and 64 deletions
+2 -3
View File
@@ -19,9 +19,8 @@ import "yunion.io/x/onecloud/pkg/apis"
type SSnapshotCreateInput struct {
apis.Meta
Name string `json:"name"`
ProjectId string `json:"project_id"`
DomainId string `json:"domain_id"`
Name string `json:"name"`
Description string `json:"description"`
DiskId string `json:"disk_id"`
StorageId string `json:"storage_id"`
+8
View File
@@ -978,6 +978,14 @@ func (self *SDisk) GetStorage() *SStorage {
return nil
}
func (self *SDisk) GetRegionDriver() (IRegionDriver, error) {
storage := self.GetStorage()
if storage == nil {
return nil, fmt.Errorf("failed to found storage for disk %s(%s)", self.Name, self.Id)
}
return storage.GetRegionDriver()
}
func (self *SDisk) GetBackupStorage() *SStorage {
if len(self.BackupStorageId) == 0 {
return nil
+13
View File
@@ -51,6 +51,19 @@ func (self *SManagedResourceBase) GetCloudaccount() *SCloudaccount {
return cp.GetCloudaccount()
}
func (self *SManagedResourceBase) GetRegionDriver() (IRegionDriver, error) {
cloudprovider := self.GetCloudprovider()
provider := api.CLOUD_PROVIDER_ONECLOUD
if cloudprovider != nil {
provider = cloudprovider.Provider
}
driver := GetRegionDriver(provider)
if driver == nil {
return nil, fmt.Errorf("failed to get %s region drivder", provider)
}
return driver, nil
}
func (self *SManagedResourceBase) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
provider := self.GetCloudprovider()
if provider == nil {
+1 -1
View File
@@ -97,7 +97,7 @@ type IRegionDriver interface {
// Region Driver Snapshot Apis
ValidateSnapshotDelete(ctx context.Context, snapshot *SSnapshot) error
ValidateSnapshotCreate(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, data *jsonutils.JSONDict) error
ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, storage *SStorage, input *api.SSnapshotCreateInput) error
RequestCreateSnapshot(ctx context.Context, snapshot *SSnapshot, task taskman.ITask) error
RequestDeleteSnapshot(ctx context.Context, snapshot *SSnapshot, task taskman.ITask) error
SnapshotIsOutOfChain(disk *SDisk) bool
+25 -47
View File
@@ -84,27 +84,6 @@ func init() {
SnapshotManager.SetVirtualObject(SnapshotManager)
}
func ValidateSnapshotName(name string, owner mcclient.IIdentityProvider) error {
q := SnapshotManager.Query()
q = SnapshotManager.FilterByName(q, name)
q = SnapshotManager.FilterByOwner(q, owner, SnapshotManager.NamespaceScope())
q = SnapshotManager.FilterBySystemAttributes(q, nil, nil, SnapshotManager.ResourceScope())
cnt, err := q.CountWithError()
if err != nil {
return err
}
if cnt != 0 {
return httperrors.NewConflictError("Name %s conflict", name)
}
if !('A' <= name[0] && name[0] <= 'Z' || 'a' <= name[0] && name[0] <= 'z') {
return httperrors.NewBadRequestError("Name must start with letter")
}
if len(name) < 2 || len(name) > 128 {
return httperrors.NewBadRequestError("Snapshot name length must within 2~128")
}
return nil
}
func (self *SSnapshotManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
return true
}
@@ -236,21 +215,40 @@ func (self *SSnapshot) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
func (manager *SSnapshotManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
diskV := validators.NewModelIdOrNameValidator("disk", "disk", ownerId)
if err := diskV.Validate(data); err != nil {
err := diskV.Validate(data)
if err != nil {
return nil, err
}
disk := diskV.Model.(*SDisk)
snapshotName, err := data.GetString("name")
if err != nil {
return nil, httperrors.NewMissingParameterError("name")
input := &api.SSnapshotCreateInput{
DiskType: disk.DiskType,
Size: disk.DiskSize,
}
err = ValidateSnapshotName(snapshotName, ownerId)
err = data.Unmarshal(input)
if err != nil {
return nil, httperrors.NewInputParameterError("failed to unmarshal input params: %v", err)
}
storage := disk.GetStorage()
if len(disk.ExternalId) == 0 {
input.StorageId = disk.StorageId
}
input.ManagerId = storage.ManagerId
region := storage.GetRegion()
if region == nil {
return nil, httperrors.NewInputParameterError("failed to found region for disk's storage %s(%s)", storage.Name, storage.Id)
}
input.CloudregionId = region.Id
driver, err := storage.GetRegionDriver()
if err != nil {
return nil, err
}
input.OutOfChain = driver.SnapshotIsOutOfChain(disk)
err = disk.GetStorage().GetRegion().GetDriver().ValidateSnapshotCreate(ctx, userCred, disk, data)
err = driver.ValidateCreateSnapshotData(ctx, userCred, disk, storage, input)
if err != nil {
return nil, err
}
@@ -262,26 +260,6 @@ func (manager *SSnapshotManager) ValidateCreateData(ctx context.Context, userCre
return nil, httperrors.NewOutOfQuotaError("Check set pending quota error %s", err)
}
input := &api.SSnapshotCreateInput{}
input.Name = snapshotName
input.ProjectId = ownerId.GetProjectId()
input.DomainId = ownerId.GetProjectDomainId()
input.DiskId = disk.Id
input.CreatedBy = api.SNAPSHOT_MANUAL
input.Size = disk.DiskSize
input.DiskType = disk.DiskType
input.OutOfChain = disk.GetStorage().GetRegion().GetDriver().SnapshotIsOutOfChain(disk)
storage := disk.GetStorage()
if len(disk.ExternalId) == 0 {
input.StorageId = disk.StorageId
}
if cloudregion := storage.GetRegion(); cloudregion != nil {
input.CloudregionId = cloudregion.GetId()
}
provider := disk.GetCloudprovider()
if provider != nil {
input.ManagerId = provider.Id
}
return input.JSON(input), nil
}
+2 -1
View File
@@ -19,6 +19,7 @@ import (
"yunion.io/x/jsonutils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/mcclient"
)
@@ -34,7 +35,7 @@ type IStorageDriver interface {
PostCreate(ctx context.Context, userCred mcclient.TokenCredential, storage *SStorage, data jsonutils.JSONObject)
ValidateSnapshotDelete(ctx context.Context, snapshot *SSnapshot) error
ValidateSnapshotCreate(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, data *jsonutils.JSONDict) error
ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, input *api.SSnapshotCreateInput) error
RequestCreateSnapshot(ctx context.Context, snapshot *SSnapshot, task taskman.ITask) error
RequestDeleteSnapshot(ctx context.Context, snapshot *SSnapshot, task taskman.ITask) error
SnapshotIsOutOfChain(disk *SDisk) bool
+2 -3
View File
@@ -845,9 +845,8 @@ func (self *SAliyunRegionDriver) ValidateCreateSnapshopolicyDiskData(ctx context
return nil
}
func (self *SAliyunRegionDriver) ValidateSnapshotCreate(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, data *jsonutils.JSONDict) error {
name, _ := data.GetString("name")
if strings.HasPrefix(name, "auto") || strings.HasPrefix(name, "http://") || strings.HasPrefix(name, "https://") {
func (self *SAliyunRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SSnapshotCreateInput) error {
if strings.HasPrefix(input.Name, "auto") || strings.HasPrefix(input.Name, "http://") || strings.HasPrefix(input.Name, "https://") {
return httperrors.NewBadRequestError(
"Snapshot for %s name can't start with auto, http:// or https://", self.GetProvider())
}
+2 -2
View File
@@ -149,8 +149,8 @@ func (self *SBaseRegionDriver) RequestDeleteSnapshot(ctx context.Context, snapsh
return fmt.Errorf("Not Implement RequestDeleteSnapshot")
}
func (self *SBaseRegionDriver) ValidateSnapshotCreate(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, data *jsonutils.JSONDict) error {
return fmt.Errorf("Not Implement ValidateSnapshotCreate")
func (self *SBaseRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SSnapshotCreateInput) error {
return fmt.Errorf("Not Implement ValidateCreateSnapshotData")
}
func (self *SBaseRegionDriver) RequestCreateSnapshot(ctx context.Context, snapshot *models.SSnapshot, task taskman.ITask) error {
+1 -1
View File
@@ -51,6 +51,6 @@ func (self *SEsxiRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx con
return nil, httperrors.NewNotImplementedError("%s does not support creating loadbalancer certificate", self.GetProvider())
}
func (self *SEsxiRegionDriver) ValidateSnapshotCreate(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, data *jsonutils.JSONDict) error {
func (self *SEsxiRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SSnapshotCreateInput) error {
return fmt.Errorf("%s does not support creating snapshot", self.GetProvider())
}
+6 -3
View File
@@ -732,9 +732,12 @@ func (self *SKVMRegionDriver) RequestDeleteSnapshot(ctx context.Context, snapsho
return models.GetStorageDriver(storage.StorageType).RequestDeleteSnapshot(ctx, snapshot, task)
}
func (self *SKVMRegionDriver) ValidateSnapshotCreate(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, data *jsonutils.JSONDict) error {
storage := disk.GetStorage()
return models.GetStorageDriver(storage.StorageType).ValidateSnapshotCreate(ctx, userCred, disk, data)
func (self *SKVMRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SSnapshotCreateInput) error {
host := storage.GetMasterHost()
if host == nil {
return fmt.Errorf("failed to get master host, maybe the host is offline")
}
return models.GetStorageDriver(storage.StorageType).ValidateCreateSnapshotData(ctx, userCred, disk, input)
}
func (self *SKVMRegionDriver) RequestCreateSnapshot(ctx context.Context, snapshot *models.SSnapshot, task taskman.ITask) error {
+1 -1
View File
@@ -1193,7 +1193,7 @@ func (self *SManagedVirtualizationRegionDriver) RequestDeleteSnapshot(ctx contex
return nil
}
func (self *SManagedVirtualizationRegionDriver) ValidateSnapshotCreate(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, data *jsonutils.JSONDict) error {
func (self *SManagedVirtualizationRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SSnapshotCreateInput) error {
return nil
}
+1 -1
View File
@@ -66,7 +66,7 @@ func (self *SBaseStorageDriver) ValidateSnapshotDelete(ctx context.Context, snap
return nil
}
func (self *SBaseStorageDriver) ValidateSnapshotCreate(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, data *jsonutils.JSONDict) error {
func (self *SBaseStorageDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, input *api.SSnapshotCreateInput) error {
guests := disk.GetGuests()
if len(guests) != 1 {
return httperrors.NewBadRequestError("Disk %s dosen't attach guest ?", disk.Id)
+1 -1
View File
@@ -179,7 +179,7 @@ func (self *SRbdStorageDriver) ValidateSnapshotDelete(ctx context.Context, snaps
return nil
}
func (self *SRbdStorageDriver) ValidateSnapshotCreate(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, data *jsonutils.JSONDict) error {
func (self *SRbdStorageDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, input *api.SSnapshotCreateInput) error {
return nil
}
@@ -23,6 +23,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/util/logclient"
)
type SnapshotCreateTask struct {
@@ -41,12 +42,14 @@ func (self *SnapshotCreateTask) OnInit(ctx context.Context, obj db.IStandaloneMo
func (self *SnapshotCreateTask) TaskFailed(ctx context.Context, snapshot *models.SSnapshot, reason string) {
snapshot.SetStatus(self.UserCred, api.SNAPSHOT_FAILED, reason)
db.OpsLog.LogEvent(snapshot, db.ACT_SNAPSHOT_FAIL, reason, self.UserCred)
logclient.AddActionLogWithStartable(self, snapshot, logclient.ACT_CREATE, reason, self.UserCred, false)
self.SetStageFailed(ctx, reason)
}
func (self *SnapshotCreateTask) TaskComplete(ctx context.Context, snapshot *models.SSnapshot, data jsonutils.JSONObject) {
snapshot.SetStatus(self.UserCred, api.SNAPSHOT_READY, "")
db.OpsLog.LogEvent(snapshot, db.ACT_SNAPSHOT_DONE, "", self.UserCred)
logclient.AddActionLogWithStartable(self, snapshot, logclient.ACT_CREATE, "", self.UserCred, true)
self.SetStageComplete(ctx, nil)
}