mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
fix: backup storage access containd by hosts (#20063)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
This commit is contained in:
@@ -83,6 +83,11 @@ type BackupStorageDetails struct {
|
||||
|
||||
type BackupStorageListInput struct {
|
||||
apis.EnabledStatusInfrasResourceBaseListInput
|
||||
|
||||
// filter by server_id
|
||||
ServerId string `json:"server_id"`
|
||||
// filter by disk_id
|
||||
DiskId string `json:"disk_id"`
|
||||
}
|
||||
|
||||
type DiskBackupListInput struct {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// 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 compute
|
||||
|
||||
type BackupstorageResourceInput struct {
|
||||
// 备份存储(ID或Name)
|
||||
BackupstorageId string `json:"backupstorage_id"`
|
||||
// swagger:ignore
|
||||
// Deprecated
|
||||
// filter by backupstorage_id
|
||||
Backupstorage string `json:"backupstorage" yunion-deprecated-by:"backupstorage_id"`
|
||||
}
|
||||
|
||||
type BackupstorageFilterListInputBase struct {
|
||||
BackupstorageResourceInput
|
||||
|
||||
// 以备份存储名称排序
|
||||
// pattern:asc|desc
|
||||
OrderByBackupstorage string `json:"order_by_backupstorage"`
|
||||
}
|
||||
|
||||
type BackupstorageResourceInfo struct {
|
||||
// 备份存储名称
|
||||
Backupstorage string `json:"backupstorage"`
|
||||
|
||||
// 备份存储类型
|
||||
BackupstorageType TBackupStorageType `json:"backupstorage_type"`
|
||||
|
||||
// 备份存储状态
|
||||
BackupstorageStatus string `json:"backupstorage_status"`
|
||||
}
|
||||
|
||||
type BackupstorageFilterListInput struct {
|
||||
BackupstorageFilterListInputBase
|
||||
}
|
||||
@@ -71,6 +71,7 @@ type HostListInput struct {
|
||||
|
||||
StorageFilterListInput
|
||||
UsableResourceListInput
|
||||
BackupstorageFilterListInput
|
||||
|
||||
// filter by ResourceType
|
||||
ResourceType string `json:"resource_type"`
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
)
|
||||
|
||||
type HostBackupstorageDetails struct {
|
||||
HostJointResourceDetails
|
||||
|
||||
SHostBackupstorage
|
||||
|
||||
// 存储名称
|
||||
Backupstorage string `json:"backupstorage"`
|
||||
// 存储大小
|
||||
CapacityMb int64 `json:"capacity_mb"`
|
||||
// 存储类型
|
||||
// example: local
|
||||
StorageType TBackupStorageType `json:"storage_type"`
|
||||
// 是否启用
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type HostBackupstorageListInput struct {
|
||||
HostJointsListInput
|
||||
|
||||
BackupstorageFilterListInput
|
||||
}
|
||||
|
||||
type HostBackupstorageCreateInput struct {
|
||||
apis.JoinResourceBaseCreateInput
|
||||
BackupstorageId string `json:"backupstorage_id"`
|
||||
HostId string `json:"host_id"`
|
||||
}
|
||||
@@ -27,7 +27,8 @@ type HostJointResourceDetailsBase struct {
|
||||
type HostJointResourceDetails struct {
|
||||
apis.JointResourceBaseDetails
|
||||
|
||||
HostJointResourceDetailsBase
|
||||
// HostJointResourceDetailsBase
|
||||
HostResourceInfo
|
||||
}
|
||||
|
||||
type HostJointsListInput struct {
|
||||
|
||||
@@ -1296,6 +1296,15 @@ type SHost struct {
|
||||
UefiInfo jsonutils.JSONObject `json:"uefi_info"`
|
||||
}
|
||||
|
||||
// SHostBackupstorage is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SHostBackupstorage.
|
||||
type SHostBackupstorage struct {
|
||||
SHostJointsBase
|
||||
// 宿主机Id
|
||||
HostId string `json:"host_id"`
|
||||
// 存储Id
|
||||
BackupstorageId string `json:"backupstorage_id"`
|
||||
}
|
||||
|
||||
// SHostIsolatedDeviceModel is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SHostIsolatedDeviceModel.
|
||||
type SHostIsolatedDeviceModel struct {
|
||||
SHostJointsBase
|
||||
|
||||
@@ -140,12 +140,16 @@ func (bs *SBackupStorage) PostCreate(ctx context.Context, userCred mcclient.Toke
|
||||
log.Errorf("convert object secret fail %s", err)
|
||||
}
|
||||
}
|
||||
err := StartResourceSyncStatusTask(ctx, userCred, bs, "BackupStorageSyncstatusTask", "")
|
||||
err := bs.startSyncStatusTask(ctx, userCred, "")
|
||||
if err != nil {
|
||||
log.Errorf("unable to sync backup storage status")
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *SBackupStorage) startSyncStatusTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
|
||||
return StartResourceSyncStatusTask(ctx, userCred, bs, "BackupStorageSyncstatusTask", parentTaskId)
|
||||
}
|
||||
|
||||
func (bs *SBackupStorage) saveObjectSecret(secret string) error {
|
||||
sec, err := utils.EncryptAESBase64(bs.Id, secret)
|
||||
if err != nil {
|
||||
@@ -189,11 +193,57 @@ func (bm *SBackupStorageManager) ListItemFilter(ctx context.Context, q *sqlchemy
|
||||
var err error
|
||||
q, err = bm.SEnabledStatusInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, input.EnabledStatusInfrasResourceBaseListInput)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
if len(input.ServerId) > 0 {
|
||||
serverObj, err := GuestManager.FetchByIdOrName(ctx, userCred, input.ServerId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == errors.ErrNotFound {
|
||||
return nil, httperrors.NewResourceNotFoundError2(GuestManager.Keyword(), input.ServerId)
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "GuestManager.FetchByIdOrName")
|
||||
}
|
||||
}
|
||||
server := serverObj.(*SGuest)
|
||||
input.ServerId = server.Id
|
||||
hostIds, err := server.getDisksCandidateHostIds()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getDisksCandidateHostIds")
|
||||
}
|
||||
q = bm.filterByCandidateHostIds(q, hostIds)
|
||||
}
|
||||
if len(input.DiskId) > 0 {
|
||||
diskObj, err := DiskManager.FetchByIdOrName(ctx, userCred, input.DiskId)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == errors.ErrNotFound {
|
||||
return nil, httperrors.NewResourceNotFoundError2(DiskManager.Keyword(), input.DiskId)
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "DiskManager.FetchByIdOrName")
|
||||
}
|
||||
}
|
||||
disk := diskObj.(*SDisk)
|
||||
input.DiskId = disk.Id
|
||||
hostIds, err := disk.getCandidateHostIds()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getDisksCandidateHostIds")
|
||||
}
|
||||
q = bm.filterByCandidateHostIds(q, hostIds)
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (bm *SBackupStorageManager) filterByCandidateHostIds(q *sqlchemy.SQuery, candidateIds []string) *sqlchemy.SQuery {
|
||||
hbsSubQ := HostBackupstorageManager.Query().SubQuery()
|
||||
|
||||
q = q.LeftJoin(hbsSubQ, sqlchemy.Equals(q.Field("id"), hbsSubQ.Field("backupstorage_id")))
|
||||
q = q.Filter(sqlchemy.OR(
|
||||
sqlchemy.IsNull(hbsSubQ.Field("host_id")),
|
||||
sqlchemy.In(hbsSubQ.Field("host_id"), candidateIds),
|
||||
))
|
||||
|
||||
return q
|
||||
}
|
||||
|
||||
func (bs *SBackupStorage) PerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.DiskBackupSyncstatusInput) (jsonutils.JSONObject, error) {
|
||||
var openTask = true
|
||||
count, err := taskman.TaskManager.QueryTasksOfObject(bs, time.Now().Add(-3*time.Minute), &openTask).CountWithError()
|
||||
@@ -204,7 +254,7 @@ func (bs *SBackupStorage) PerformSyncstatus(ctx context.Context, userCred mcclie
|
||||
return nil, httperrors.NewBadRequestError("Backup has %d task active, can't sync status", count)
|
||||
}
|
||||
|
||||
return nil, StartResourceSyncStatusTask(ctx, userCred, bs, "BackupStorageSyncstatusTask", "")
|
||||
return nil, bs.startSyncStatusTask(ctx, userCred, "")
|
||||
}
|
||||
|
||||
func (bs *SBackupStorage) ValidateUpdateData(
|
||||
@@ -295,3 +345,23 @@ func (bs *SBackupStorage) GetAccessInfo() (*api.SBackupStorageAccessInfo, error)
|
||||
}
|
||||
return &accessInfo, nil
|
||||
}
|
||||
|
||||
func (bs *SBackupStorage) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
log.Infof("Host delete do nothing")
|
||||
// cleanup hostbackupstorage
|
||||
hbs, err := HostBackupstorageManager.GetBackupStoragesByBackup(bs.Id)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetBackupStoragesByBackup")
|
||||
}
|
||||
var errs []error
|
||||
for i := range hbs {
|
||||
err := hbs[i].Detach(ctx, userCred)
|
||||
if err != nil {
|
||||
errs = append(errs, errors.Wrapf(err, "Detach %s %s", hbs[i].HostId, hbs[i].BackupstorageId))
|
||||
}
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return errors.NewAggregate(errs)
|
||||
}
|
||||
return bs.SEnabledStatusInfrasResourceBase.Delete(ctx, userCred)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
// 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 models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/reflectutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SBackupstorageResourceBase struct {
|
||||
BackupstorageId string `width:"36" charset:"ascii" nullable:"true" list:"user" index:"true" create:"optional"`
|
||||
}
|
||||
|
||||
type SBackupstorageResourceBaseManager struct {
|
||||
}
|
||||
|
||||
func ValidateBackupstorageResourceInput(ctx context.Context, userCred mcclient.TokenCredential, query api.BackupstorageResourceInput) (*SBackupStorage, api.BackupstorageResourceInput, error) {
|
||||
storageObj, err := BackupStorageManager.FetchByIdOrName(ctx, userCred, query.BackupstorageId)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, query, errors.Wrapf(httperrors.ErrResourceNotFound, "%s %s", BackupStorageManager.Keyword(), query.BackupstorageId)
|
||||
} else {
|
||||
return nil, query, errors.Wrap(err, "BackupStorageManager.FetchByIdOrName")
|
||||
}
|
||||
}
|
||||
query.BackupstorageId = storageObj.GetId()
|
||||
return storageObj.(*SBackupStorage), query, nil
|
||||
}
|
||||
|
||||
func (self *SBackupstorageResourceBase) GetBackupstorage() *SBackupStorage {
|
||||
obj, err := BackupStorageManager.FetchById(self.BackupstorageId)
|
||||
if err != nil {
|
||||
log.Errorf("fail to fetch storage by id: %s: %s", self.BackupstorageId, err)
|
||||
return nil
|
||||
}
|
||||
return obj.(*SBackupStorage)
|
||||
}
|
||||
|
||||
func (manager *SBackupstorageResourceBaseManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.BackupstorageResourceInfo {
|
||||
rows := make([]api.BackupstorageResourceInfo, len(objs))
|
||||
storageIds := make([]string, len(objs))
|
||||
for i := range objs {
|
||||
var base *SBackupstorageResourceBase
|
||||
reflectutils.FindAnonymouStructPointer(objs[i], &base)
|
||||
if base != nil {
|
||||
storageIds[i] = base.BackupstorageId
|
||||
}
|
||||
}
|
||||
|
||||
storages := make(map[string]SBackupStorage)
|
||||
err := db.FetchStandaloneObjectsByIds(BackupStorageManager, storageIds, &storages)
|
||||
if err != nil {
|
||||
log.Errorf("FetchStandaloneObjectsByIds fail %s", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := range rows {
|
||||
rows[i] = api.BackupstorageResourceInfo{}
|
||||
if _, ok := storages[storageIds[i]]; ok {
|
||||
storage := storages[storageIds[i]]
|
||||
rows[i].Backupstorage = storage.Name
|
||||
rows[i].BackupstorageStatus = storage.Status
|
||||
rows[i].BackupstorageType = storage.StorageType
|
||||
}
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func (manager *SBackupstorageResourceBaseManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.BackupstorageFilterListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
if len(query.BackupstorageId) > 0 {
|
||||
storageObj, _, err := ValidateBackupstorageResourceInput(ctx, userCred, query.BackupstorageResourceInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "ValidateBackupstorageResourceInput")
|
||||
}
|
||||
q = q.Equals("backupstorage_id", storageObj.GetId())
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SBackupstorageResourceBaseManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
switch field {
|
||||
case "backupstorage":
|
||||
storages := BackupStorageManager.Query("name", "id").Distinct().SubQuery()
|
||||
q.AppendField(storages.Field("name", field))
|
||||
q = q.Join(storages, sqlchemy.Equals(q.Field("backupstorage_id"), storages.Field("id")))
|
||||
q.GroupBy(storages.Field("name"))
|
||||
return q, nil
|
||||
case "storage_type":
|
||||
storages := BackupStorageManager.Query(field, "id").Distinct().SubQuery()
|
||||
q.AppendField(storages.Field(field))
|
||||
q = q.Join(storages, sqlchemy.Equals(q.Field("backupstorage_id"), storages.Field("id")))
|
||||
q.GroupBy(storages.Field(field))
|
||||
return q, nil
|
||||
}
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (manager *SBackupstorageResourceBaseManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.BackupstorageFilterListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
if !db.NeedOrderQuery(manager.GetOrderByFields(query)) {
|
||||
return q, nil
|
||||
}
|
||||
orderQ := BackupStorageManager.Query("id")
|
||||
orderSubQ := orderQ.SubQuery()
|
||||
orderQ, orders, fields := manager.GetOrderBySubQuery(orderQ, orderSubQ, orderQ.Field("id"), userCred, query, nil, nil)
|
||||
q = q.LeftJoin(orderSubQ, sqlchemy.Equals(q.Field("backupstorage_id"), orderSubQ.Field("id")))
|
||||
q = db.OrderByFields(q, orders, fields)
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SBackupstorageResourceBaseManager) GetOrderBySubQuery(
|
||||
q *sqlchemy.SQuery,
|
||||
subq *sqlchemy.SSubQuery,
|
||||
joinField sqlchemy.IQueryField,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.BackupstorageFilterListInput,
|
||||
orders []string,
|
||||
fields []sqlchemy.IQueryField,
|
||||
) (*sqlchemy.SQuery, []string, []sqlchemy.IQueryField) {
|
||||
if !db.NeedOrderQuery(manager.GetOrderByFields(query)) {
|
||||
return q, orders, fields
|
||||
}
|
||||
backupStorageQ := BackupStorageManager.Query().SubQuery()
|
||||
q = q.LeftJoin(backupStorageQ, sqlchemy.Equals(joinField, backupStorageQ.Field("id")))
|
||||
q = q.AppendField(backupStorageQ.Field("name").Label("backupstorage"))
|
||||
orders = append(orders, query.OrderByBackupstorage)
|
||||
fields = append(fields, subq.Field("backupstorage"))
|
||||
return q, orders, fields
|
||||
}
|
||||
|
||||
func (manager *SBackupstorageResourceBaseManager) GetOrderByFields(query api.BackupstorageFilterListInput) []string {
|
||||
fields := make([]string, 0)
|
||||
fields = append(fields, query.OrderByBackupstorage)
|
||||
return fields
|
||||
}
|
||||
|
||||
func (manager *SBackupstorageResourceBaseManager) ListItemExportKeys(ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
keys stringutils2.SSortedStrings,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
if keys.ContainsAny(manager.GetExportKeys()...) {
|
||||
subq := BackupStorageManager.Query("id", "name").SubQuery()
|
||||
q = q.LeftJoin(subq, sqlchemy.Equals(q.Field("backupstorage_id"), subq.Field("id")))
|
||||
if keys.Contains("backupstorage") {
|
||||
q = q.AppendField(subq.Field("name", "backupstorage"))
|
||||
}
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SBackupstorageResourceBaseManager) GetExportKeys() []string {
|
||||
keys := []string{"backupstorage"}
|
||||
return keys
|
||||
}
|
||||
|
||||
func (model *SBackupstorageResourceBase) GetChangeOwnerCandidateDomainIds() []string {
|
||||
storage := model.GetBackupstorage()
|
||||
if storage != nil {
|
||||
return storage.GetChangeOwnerCandidateDomainIds()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -1396,6 +1396,18 @@ func (self *SDisk) GetPathAtHost(host *SHost) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (disk *SDisk) getCandidateHostIds() ([]string, error) {
|
||||
hss, err := HoststorageManager.GetHostStoragesByStorageId(disk.StorageId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetHostStoragesByStorageId")
|
||||
}
|
||||
candidates := make([]string, 0)
|
||||
for i := range hss {
|
||||
candidates = append(candidates, hss[i].HostId)
|
||||
}
|
||||
return candidates, nil
|
||||
}
|
||||
|
||||
func (self *SDisk) GetMasterHost(storage *SStorage) (*SHost, error) {
|
||||
if storage.MasterHost != "" {
|
||||
return storage.GetMasterHost()
|
||||
|
||||
@@ -6815,3 +6815,24 @@ func (guest *SGuest) IsSriov() bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (guest *SGuest) getDisksCandidateHostIds() ([]string, error) {
|
||||
disks, err := guest.GetDisks()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "guest.GetDisks")
|
||||
}
|
||||
ret := stringutils2.NewSortedStrings(nil)
|
||||
for i := range disks {
|
||||
candidates, err := disks[i].getCandidateHostIds()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getCandidateHostIds")
|
||||
}
|
||||
sorted := stringutils2.NewSortedStrings(candidates)
|
||||
if i > 0 {
|
||||
ret = stringutils2.Intersect(ret, sorted)
|
||||
} else {
|
||||
ret = sorted
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
// 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 models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SHostBackupstorageManager struct {
|
||||
SHostJointsManager
|
||||
SBackupstorageResourceBaseManager
|
||||
}
|
||||
|
||||
var HostBackupstorageManager *SHostBackupstorageManager
|
||||
|
||||
func init() {
|
||||
db.InitManager(func() {
|
||||
HostBackupstorageManager = &SHostBackupstorageManager{
|
||||
SHostJointsManager: NewHostJointsManager(
|
||||
"host_id",
|
||||
SHostBackupstorage{},
|
||||
"hostbackupstorages_tbl",
|
||||
"hostbackupstorage",
|
||||
"hostbackupstorages",
|
||||
BackupStorageManager,
|
||||
),
|
||||
}
|
||||
HostBackupstorageManager.SetVirtualObject(HostBackupstorageManager)
|
||||
HostBackupstorageManager.TableSpec().AddIndex(false, "host_id", "backupstorage_id")
|
||||
})
|
||||
}
|
||||
|
||||
type SHostBackupstorage struct {
|
||||
SHostJointsBase
|
||||
|
||||
// 宿主机Id
|
||||
HostId string `width:"36" charset:"ascii" nullable:"false" list:"domain" create:"required" json:"host_id"`
|
||||
// 存储Id
|
||||
BackupstorageId string `width:"36" charset:"ascii" nullable:"false" list:"domain" create:"required" json:"backupstorage_id" index:"true"`
|
||||
}
|
||||
|
||||
func (manager *SHostBackupstorageManager) GetMasterFieldName() string {
|
||||
return "host_id"
|
||||
}
|
||||
|
||||
func (manager *SHostBackupstorageManager) GetSlaveFieldName() string {
|
||||
return "backupstorage_id"
|
||||
}
|
||||
|
||||
func (manager *SHostBackupstorageManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.HostBackupstorageDetails {
|
||||
rows := make([]api.HostBackupstorageDetails, len(objs))
|
||||
|
||||
hostRows := manager.SHostJointsManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
backupStorageIds := make([]string, len(rows))
|
||||
|
||||
for i := range rows {
|
||||
rows[i] = api.HostBackupstorageDetails{
|
||||
HostJointResourceDetails: hostRows[i],
|
||||
}
|
||||
backupStorageIds[i] = objs[i].(*SHostBackupstorage).BackupstorageId
|
||||
}
|
||||
|
||||
backupStorages := make(map[string]SBackupStorage)
|
||||
err := db.FetchStandaloneObjectsByIds(BackupStorageManager, backupStorageIds, &backupStorages)
|
||||
if err != nil {
|
||||
log.Errorf("db.FetchStandaloneObjectsByIds fail %s", err)
|
||||
return rows
|
||||
}
|
||||
|
||||
for i := range rows {
|
||||
if bs, ok := backupStorages[backupStorageIds[i]]; ok {
|
||||
rows[i] = objs[i].(*SHostBackupstorage).getExtraDetails(bs, rows[i])
|
||||
}
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func (hb *SHostBackupstorage) GetHost() *SHost {
|
||||
host, _ := HostManager.FetchById(hb.HostId)
|
||||
if host != nil {
|
||||
return host.(*SHost)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hb *SHostBackupstorage) GetBackupStorage() *SBackupStorage {
|
||||
bs, err := BackupStorageManager.FetchById(hb.BackupstorageId)
|
||||
if err != nil {
|
||||
log.Errorf("Hoststorage fetch storage %q error: %v", hb.BackupstorageId, err)
|
||||
}
|
||||
if bs != nil {
|
||||
return bs.(*SBackupStorage)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (manager *SHostBackupstorageManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.HostBackupstorageCreateInput) (api.HostBackupstorageCreateInput, error) {
|
||||
{
|
||||
backStorageObj, err := validators.ValidateModel(ctx, userCred, BackupStorageManager, &input.BackupstorageId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
backupStorage := backStorageObj.(*SBackupStorage)
|
||||
input.BackupstorageId = backupStorage.Id
|
||||
}
|
||||
{
|
||||
hostObj, err := validators.ValidateModel(ctx, userCred, HostManager, &input.HostId)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
host := hostObj.(*SHost)
|
||||
input.HostId = host.Id
|
||||
}
|
||||
{
|
||||
hs, err := manager.GetBackupStoragesByHost(input.HostId, api.BACKUPSTORAGE_TYPE_NFS)
|
||||
if err != nil {
|
||||
return input, errors.Wrap(err, "GetBackupStoragesByHost")
|
||||
}
|
||||
if len(hs) >= 1 {
|
||||
return input, errors.Wrapf(httperrors.ErrResourceBusy, "host %s has been attached to a NFS backupstorage", input.HostId)
|
||||
}
|
||||
}
|
||||
var err error
|
||||
input.JoinResourceBaseCreateInput, err = manager.SJointResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.JoinResourceBaseCreateInput)
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (hb *SHostBackupstorage) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
hb.SHostJointsBase.PostCreate(ctx, userCred, ownerId, query, data)
|
||||
|
||||
bs := hb.GetBackupStorage()
|
||||
if bs != nil {
|
||||
bs.startSyncStatusTask(ctx, userCred, "")
|
||||
}
|
||||
}
|
||||
|
||||
func (hb *SHostBackupstorage) PostDelete(ctx context.Context, userCred mcclient.TokenCredential) {
|
||||
hb.SHostJointsBase.PostDelete(ctx, userCred)
|
||||
|
||||
bs := hb.GetBackupStorage()
|
||||
if bs != nil {
|
||||
bs.startSyncStatusTask(ctx, userCred, "")
|
||||
}
|
||||
}
|
||||
|
||||
func (hb *SHostBackupstorage) getExtraDetails(storage SBackupStorage, out api.HostBackupstorageDetails) api.HostBackupstorageDetails {
|
||||
out.Backupstorage = storage.Name
|
||||
out.CapacityMb = int64(storage.CapacityMb)
|
||||
out.StorageType = storage.StorageType
|
||||
out.Enabled = storage.Enabled.Bool()
|
||||
return out
|
||||
}
|
||||
|
||||
func (hb *SHostBackupstorage) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
|
||||
return hb.SHostJointsBase.ValidateDeleteCondition(ctx, nil)
|
||||
}
|
||||
|
||||
func (hb *SHostBackupstorage) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DeleteModel(ctx, userCred, hb)
|
||||
}
|
||||
|
||||
func (hb *SHostBackupstorage) Detach(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DetachJoint(ctx, userCred, hb)
|
||||
}
|
||||
|
||||
func (manager *SHostBackupstorageManager) GetBackupStoragesByBackup(backupStorageId string) ([]SHostBackupstorage, error) {
|
||||
hoststorages := make([]SHostBackupstorage, 0)
|
||||
q := HostBackupstorageManager.Query().Equals("backupstorage_id", backupStorageId)
|
||||
err := db.FetchModelObjects(manager, q, &hoststorages)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hoststorages, nil
|
||||
}
|
||||
|
||||
func (manager *SHostBackupstorageManager) GetBackupStoragesByHost(hostId string, backupType api.TBackupStorageType) ([]SHostBackupstorage, error) {
|
||||
hoststorages := make([]SHostBackupstorage, 0)
|
||||
backups := BackupStorageManager.Query().Equals("storage_type", backupType).SubQuery()
|
||||
q := HostBackupstorageManager.Query().Equals("host_id", hostId)
|
||||
q = q.Join(backups, sqlchemy.Equals(q.Field("backupstorage_id"), backups.Field("id")))
|
||||
err := db.FetchModelObjects(manager, q, &hoststorages)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hoststorages, nil
|
||||
}
|
||||
|
||||
func (manager *SHostBackupstorageManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.HostBackupstorageListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SHostJointsManager.ListItemFilter(ctx, q, userCred, query.HostJointsListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SHostResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
q, err = manager.SBackupstorageResourceBaseManager.ListItemFilter(ctx, q, userCred, query.BackupstorageFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SBackupstorageResourceBaseManager.ListItemFilter")
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SHostBackupstorageManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.HostBackupstorageListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SHostJointsManager.OrderByExtraFields(ctx, q, userCred, query.HostJointsListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SHostResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SBackupstorageResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.BackupstorageFilterListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SBackupstorageResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SHostBackupstorageManager) ListItemExportKeys(ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
keys stringutils2.SSortedStrings,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SHostJointsManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SHostJointsManager.ListItemExportKeys")
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
@@ -63,10 +63,12 @@ func (manager *SHostJointsManager) FetchCustomizeColumns(
|
||||
rows := make([]api.HostJointResourceDetails, len(objs))
|
||||
|
||||
jointRows := manager.SJointResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
hostRows := manager.SHostResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
|
||||
for i := range rows {
|
||||
rows[i] = api.HostJointResourceDetails{
|
||||
JointResourceBaseDetails: jointRows[i],
|
||||
HostResourceInfo: hostRows[i],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,6 +75,8 @@ type SHostManager struct {
|
||||
SZoneResourceBaseManager
|
||||
SManagedResourceBaseManager
|
||||
SHostnameResourceBaseManager
|
||||
|
||||
SBackupstorageResourceBaseManager
|
||||
}
|
||||
|
||||
var HostManager *SHostManager
|
||||
@@ -334,6 +336,22 @@ func (manager *SHostManager) ListItemFilter(
|
||||
}
|
||||
}
|
||||
|
||||
if len(query.BackupstorageId) > 0 {
|
||||
hbsQ := HostBackupstorageManager.Query("host_id", "backupstorage_id")
|
||||
hbsQ, err = manager.SBackupstorageResourceBaseManager.ListItemFilter(ctx, hbsQ, userCred, query.BackupstorageFilterListInput)
|
||||
if err != nil {
|
||||
return q, errors.Wrap(err, "SBackupStorageResouceBaseManager.ListItemFiled")
|
||||
}
|
||||
hbsSubQ := hbsQ.SubQuery()
|
||||
q = q.LeftJoin(hbsSubQ, sqlchemy.Equals(q.Field("id"), hbsSubQ.Field("host_id")))
|
||||
notAttached := (query.StorageNotAttached != nil && *query.StorageNotAttached)
|
||||
if !notAttached {
|
||||
q = q.Filter(sqlchemy.IsNotNull(hbsSubQ.Field("backupstorage_id")))
|
||||
} else {
|
||||
q = q.Filter(sqlchemy.IsNull(hbsSubQ.Field("backupstorage_id")))
|
||||
}
|
||||
}
|
||||
|
||||
hostStorageType := query.HostStorageType
|
||||
if len(hostStorageType) > 0 {
|
||||
hoststorages := HoststorageManager.Query()
|
||||
@@ -1530,8 +1548,69 @@ func (hh *SHost) getAttachedWires() []SWire {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (hh *SHostManager) GetEnabledKvmHost() (*SHost, error) {
|
||||
hostq := HostManager.Query().IsTrue("enabled").Equals("host_status", api.HOST_ONLINE).In("host_type", []string{api.HOST_TYPE_HYPERVISOR, api.HOST_TYPE_KVM})
|
||||
func (hh *SHostManager) GetEnabledKvmHostForBackupStorage(bs *SBackupStorage) (*SHost, error) {
|
||||
hbs, err := HostBackupstorageManager.GetBackupStoragesByBackup(bs.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetBackupStoragesByBackup")
|
||||
}
|
||||
candidates := make([]string, 0)
|
||||
for i := range hbs {
|
||||
candidates = append(candidates, hbs[i].HostId)
|
||||
}
|
||||
host, err := HostManager.GetEnabledKvmHost(candidates)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetEnabledKvmHost")
|
||||
}
|
||||
return host, nil
|
||||
}
|
||||
|
||||
func (hh *SHostManager) GetEnabledKvmHostForDiskBackup(backup *SDiskBackup) (*SHost, error) {
|
||||
bs, err := backup.GetBackupStorage()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to get backupStorage")
|
||||
}
|
||||
storage, err := backup.GetStorage()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to get storage of diskbackup")
|
||||
}
|
||||
|
||||
hbs, err := HostBackupstorageManager.GetBackupStoragesByBackup(bs.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "HostBackupstorageManager.GetBackupStoragesByBackup")
|
||||
}
|
||||
hbsCandidates := stringutils2.NewSortedStrings(nil)
|
||||
for i := range hbs {
|
||||
hbsCandidates = hbsCandidates.Append(hbs[i].HostId)
|
||||
}
|
||||
hss, err := HoststorageManager.GetHostStoragesByStorageId(storage.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "HoststorageManager.GetStorages")
|
||||
}
|
||||
hssCandidates := stringutils2.NewSortedStrings(nil)
|
||||
for i := range hss {
|
||||
hssCandidates = hssCandidates.Append(hss[i].HostId)
|
||||
}
|
||||
var candidates []string
|
||||
if len(hbsCandidates) == 0 {
|
||||
candidates = []string(hssCandidates)
|
||||
} else {
|
||||
candidates = []string(stringutils2.Intersect(hbsCandidates, hssCandidates))
|
||||
}
|
||||
|
||||
host, err := HostManager.GetEnabledKvmHost(candidates)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetEnabledKvmHost")
|
||||
}
|
||||
return host, nil
|
||||
}
|
||||
|
||||
func (hh *SHostManager) GetEnabledKvmHost(candidates []string) (*SHost, error) {
|
||||
hostq := HostManager.Query().IsTrue("enabled")
|
||||
hostq = hostq.Equals("host_status", api.HOST_ONLINE)
|
||||
hostq = hostq.In("host_type", []string{api.HOST_TYPE_HYPERVISOR, api.HOST_TYPE_KVM})
|
||||
if len(candidates) > 0 {
|
||||
hostq = hostq.In("id", candidates)
|
||||
}
|
||||
host := SHost{}
|
||||
err := hostq.First(&host)
|
||||
if err != nil {
|
||||
|
||||
@@ -312,12 +312,22 @@ func (self *SHoststorage) Detach(ctx context.Context, userCred mcclient.TokenCre
|
||||
return db.DetachJoint(ctx, userCred, self)
|
||||
}
|
||||
|
||||
func (manager *SHoststorageManager) GetStorages(hostId string) ([]SHoststorage, error) {
|
||||
func (manager *SHoststorageManager) GetHostStoragesByHostId(hostId string) ([]SHoststorage, error) {
|
||||
hoststorage := make([]SHoststorage, 0)
|
||||
hoststorages := HoststorageManager.Query().SubQuery()
|
||||
err := hoststorages.Query().Equals("host_id", hostId).All(&hoststorage)
|
||||
hoststoragesQ := HoststorageManager.Query().Equals("host_id", hostId)
|
||||
err := db.FetchModelObjects(manager, hoststoragesQ, &hoststorage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "FetchModelObjects")
|
||||
}
|
||||
return hoststorage, nil
|
||||
}
|
||||
|
||||
func (manager *SHoststorageManager) GetHostStoragesByStorageId(storageId string) ([]SHoststorage, error) {
|
||||
hoststorage := make([]SHoststorage, 0)
|
||||
hoststoragesQ := HoststorageManager.Query().Equals("storage_id", storageId)
|
||||
err := db.FetchModelObjects(manager, hoststoragesQ, &hoststorage)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "FetchModelObjects")
|
||||
}
|
||||
return hoststorage, nil
|
||||
}
|
||||
|
||||
@@ -674,6 +674,7 @@ func (self *SZone) purgeHosts(ctx context.Context, managerId string) error {
|
||||
hosts := HostManager.Query("id").Equals("manager_id", managerId).Equals("zone_id", self.Id)
|
||||
isolateds := IsolatedDeviceManager.Query("id").In("host_id", hosts.SubQuery())
|
||||
hoststorages := HoststorageManager.Query("row_id").In("host_id", hosts.SubQuery())
|
||||
hostbackupStorages := HostBackupstorageManager.Query("row_id").In("host_id", hosts.SubQuery())
|
||||
hostwires := HostwireManagerDeprecated.Query("row_id").In("host_id", hosts.SubQuery())
|
||||
guests := GuestManager.Query("id").In("host_id", hosts.SubQuery())
|
||||
guestdisks := GuestdiskManager.Query("row_id").In("guest_id", guests.SubQuery())
|
||||
@@ -722,6 +723,7 @@ func (self *SZone) purgeHosts(ctx context.Context, managerId string) error {
|
||||
{manager: InstanceBackupManager, key: "id", q: instancebackups},
|
||||
{manager: GuestManager, key: "id", q: guests},
|
||||
{manager: HoststorageManager, key: "row_id", q: hoststorages},
|
||||
{manager: HostBackupstorageManager, key: "row_id", q: hostbackupStorages},
|
||||
{manager: HostwireManagerDeprecated, key: "row_id", q: hostwires},
|
||||
{manager: IsolatedDeviceManager, key: "id", q: isolateds},
|
||||
{manager: HostManager, key: "id", q: hosts},
|
||||
@@ -738,6 +740,7 @@ func (self *SZone) purgeHosts(ctx context.Context, managerId string) error {
|
||||
func (self *SHost) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
isolateds := IsolatedDeviceManager.Query("id").Equals("host_id", self.Id)
|
||||
hoststorages := HoststorageManager.Query("row_id").Equals("host_id", self.Id)
|
||||
hostbackupStorages := HostBackupstorageManager.Query("row_id").Equals("host_id", self.Id)
|
||||
hostwires := HostwireManagerDeprecated.Query("row_id").Equals("host_id", self.Id)
|
||||
guests := GuestManager.Query("id").Equals("host_id", self.Id)
|
||||
guestdisks := GuestdiskManager.Query("row_id").In("guest_id", guests.SubQuery())
|
||||
@@ -778,6 +781,7 @@ func (self *SHost) purge(ctx context.Context, userCred mcclient.TokenCredential)
|
||||
{manager: InstanceBackupManager, key: "id", q: instancebackups},
|
||||
{manager: GuestManager, key: "id", q: guests},
|
||||
{manager: HoststorageManager, key: "row_id", q: hoststorages},
|
||||
{manager: HostBackupstorageManager, key: "row_id", q: hostbackupStorages},
|
||||
{manager: HostwireManagerDeprecated, key: "row_id", q: hostwires},
|
||||
{manager: IsolatedDeviceManager, key: "id", q: isolateds},
|
||||
}
|
||||
|
||||
@@ -940,17 +940,11 @@ func (self *SKVMRegionDriver) RequestPackInstanceBackup(ctx context.Context, ib
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to get backups")
|
||||
}
|
||||
storage, err := backups[0].GetStorage()
|
||||
host, err := models.HostManager.GetEnabledKvmHostForDiskBackup(&backups[0])
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetStorage")
|
||||
}
|
||||
host, _ := storage.GetMasterHost()
|
||||
if host == nil {
|
||||
host, err = models.HostManager.GetEnabledKvmHost()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to GetEnabledKvmHost")
|
||||
}
|
||||
return errors.Wrap(err, "GetEnabledKvmHostForDiskBackup")
|
||||
}
|
||||
|
||||
backupIds := make([]string, len(backups))
|
||||
for i := range backupIds {
|
||||
backupIds[i] = backups[i].GetId()
|
||||
@@ -984,7 +978,7 @@ func (self *SKVMRegionDriver) RequestUnpackInstanceBackup(ctx context.Context, i
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to get backupStorage")
|
||||
}
|
||||
host, err := models.HostManager.GetEnabledKvmHost()
|
||||
host, err := models.HostManager.GetEnabledKvmHostForBackupStorage(backupStorage)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to GetEnabledKvmHost")
|
||||
}
|
||||
@@ -1011,9 +1005,9 @@ func (self *SKVMRegionDriver) RequestUnpackInstanceBackup(ctx context.Context, i
|
||||
|
||||
func (self *SKVMRegionDriver) RequestSyncBackupStorageStatus(ctx context.Context, userCred mcclient.TokenCredential, bs *models.SBackupStorage, task taskman.ITask) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
host, err := models.HostManager.GetEnabledKvmHost()
|
||||
host, err := models.HostManager.GetEnabledKvmHostForBackupStorage(bs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to GetEnabledKvmHost")
|
||||
return nil, errors.Wrap(err, "GetEnabledKvmHostForBackupStorage")
|
||||
}
|
||||
url := fmt.Sprintf("%s/storages/sync-backup-storage", host.ManagerUri)
|
||||
body := jsonutils.NewDict()
|
||||
@@ -1083,7 +1077,7 @@ func (self *SKVMRegionDriver) RequestSyncDiskBackupStatus(ctx context.Context, u
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to get backupStorage")
|
||||
}
|
||||
storage, _ := backup.GetStorage()
|
||||
/*storage, _ := backup.GetStorage()
|
||||
var host *models.SHost
|
||||
if storage != nil {
|
||||
host, _ = storage.GetMasterHost()
|
||||
@@ -1093,6 +1087,10 @@ func (self *SKVMRegionDriver) RequestSyncDiskBackupStatus(ctx context.Context, u
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to GetEnabledKvmHost")
|
||||
}
|
||||
}*/
|
||||
host, err := models.HostManager.GetEnabledKvmHostForDiskBackup(backup)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetEnabledKvmHostForDiskBackup")
|
||||
}
|
||||
log.Infof("host: %s, ManagerUri: %s", host.GetId(), host.ManagerUri)
|
||||
url := fmt.Sprintf("%s/storages/sync-backup", host.ManagerUri)
|
||||
@@ -1300,17 +1298,11 @@ func (self *SKVMRegionDriver) RequestDeleteBackup(ctx context.Context, backup *m
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to get backupStorage")
|
||||
}
|
||||
storage, _ := backup.GetStorage()
|
||||
var host *models.SHost
|
||||
if storage != nil {
|
||||
host, _ = storage.GetMasterHost()
|
||||
}
|
||||
if host == nil {
|
||||
host, err = models.HostManager.GetEnabledKvmHost()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to GetEnabledKvmHost")
|
||||
}
|
||||
host, err := models.HostManager.GetEnabledKvmHostForDiskBackup(backup)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetEnabledKvmHostForDiskBackup")
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/storages/delete-backup", host.ManagerUri)
|
||||
body := jsonutils.NewDict()
|
||||
body.Set("backup_id", jsonutils.NewString(backup.GetId()))
|
||||
|
||||
@@ -252,6 +252,7 @@ func InitHandlers(app *appsrv.Application) {
|
||||
models.HostwireManagerDeprecated,
|
||||
models.HostnetworkManager,
|
||||
models.HoststorageManager,
|
||||
models.HostBackupstorageManager,
|
||||
models.HostschedtagManager,
|
||||
models.HostIsolatedDeviceModelManager,
|
||||
models.StorageschedtagManager,
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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 compute
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
|
||||
var (
|
||||
HostBackupstorages modulebase.JointResourceManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
HostBackupstorages = modules.NewJointComputeManager("hostbackupstorage", "hostbackupstorages",
|
||||
[]string{"Host_ID", "Host", "Backupstorage_ID",
|
||||
"Backupstorage", "Capacity_Mb", "Host_Status", "Backupstorage_Status"},
|
||||
[]string{},
|
||||
&Hosts,
|
||||
&BackupStorages)
|
||||
modules.RegisterCompute(&HostBackupstorages)
|
||||
}
|
||||
Reference in New Issue
Block a user