mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-07-01 01:36:11 +08:00
Merge pull request #2672 from Mjoycarry/feature/snapshotpolicy_of_disk_sync
local snapshotpolicy
This commit is contained in:
@@ -259,33 +259,6 @@ func init() {
|
||||
printObject(disk)
|
||||
return nil
|
||||
})
|
||||
type DiskApplySnapshotPolicy struct {
|
||||
ID string `help:"ID or name of disk" json:"-"`
|
||||
Snapshotpolicy string `help:"ID or name of snapshot policy"`
|
||||
}
|
||||
R(&DiskApplySnapshotPolicy{}, "disk-apply-snapshot-policy", "Set disk snapshot policy", func(s *mcclient.ClientSession, args *DiskApplySnapshotPolicy) error {
|
||||
params, err := options.StructToParams(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
disk, err := modules.Disks.PerformAction(s, args.ID, "apply-snapshot-policy", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(disk)
|
||||
return nil
|
||||
})
|
||||
type DiskCancelSnapshotPolicy struct {
|
||||
ID string `help:"ID or name of disk"`
|
||||
}
|
||||
R(&DiskCancelSnapshotPolicy{}, "disk-cancel-snapshot-policy", "Cancel disk snapshot policy", func(s *mcclient.ClientSession, args *DiskCancelSnapshotPolicy) error {
|
||||
disk, err := modules.Disks.PerformAction(s, args.ID, "cancel-snapshot-policy", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(disk)
|
||||
return nil
|
||||
})
|
||||
|
||||
type DiskChangeOwnerOptions struct {
|
||||
ID string `help:"Disk to change owner" json:"-"`
|
||||
|
||||
@@ -16,6 +16,7 @@ package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/options"
|
||||
@@ -51,9 +52,7 @@ func init() {
|
||||
})
|
||||
|
||||
type SnapshotPolicyCreateOptions struct {
|
||||
NAME string
|
||||
Manager string `help:"Manager id or name"`
|
||||
Cloudregion string `help:"Cloudregion id or name"`
|
||||
NAME string
|
||||
|
||||
RetentionDays int `help:"snapshot retention days"`
|
||||
RepeatWeekdays []int `help:"snapshot create days on week"`
|
||||
@@ -70,21 +69,36 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type SnapshotPolicyApplyOptions struct {
|
||||
ID string `help:"ID or Name of SnapshotPolicy" json:"-"`
|
||||
Disk []string `help:"Disks id to apply snapshot policy"`
|
||||
type SnapshotPolicyBindDisksOptions struct {
|
||||
ID string `help:"ID"`
|
||||
Disk []string `help:"ids of disk"`
|
||||
}
|
||||
|
||||
R(&SnapshotPolicyApplyOptions{}, "snapshot-policy-apply", "Apply snapshot policy to disks", func(s *mcclient.ClientSession, args *SnapshotPolicyApplyOptions) error {
|
||||
params, err := options.StructToParams(args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
snapshot, err := modules.SnapshotPoliciy.PerformAction(s, args.ID, "apply-to-disk", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(snapshot)
|
||||
return nil
|
||||
})
|
||||
R(&SnapshotPolicyBindDisksOptions{}, "snapshot-policy-bind-disk", "bind snapshotpolicy to disks",
|
||||
func(s *mcclient.ClientSession, opts *SnapshotPolicyBindDisksOptions) error {
|
||||
params, err := options.StructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sp, err := modules.SnapshotPoliciy.PerformAction(s, opts.ID, "bind-disks", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(sp)
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&SnapshotPolicyBindDisksOptions{}, "snapshot-policy-unbind-disk", "bind snapshotpolicy to disks",
|
||||
func(s *mcclient.ClientSession, opts *SnapshotPolicyBindDisksOptions) error {
|
||||
params, err := options.StructToParams(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sp, err := modules.SnapshotPoliciy.PerformAction(s, opts.ID, "unbind-disks", params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(sp)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/mcclient/modules"
|
||||
)
|
||||
@@ -76,5 +77,4 @@ func init() {
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -254,6 +254,21 @@ paths:
|
||||
/natsentries/{snatentryId}:
|
||||
$ref: "./natgateway/snatentry.yaml"
|
||||
|
||||
/snapshotpolicies:
|
||||
$ref: "./snapshotpolicy/snapshotpolicies.yaml"
|
||||
/snapshotpolicies/{snapshotpolicyId}:
|
||||
$ref: "./snapshotpolicy/snapshotpolicy.yaml"
|
||||
/disks/{disk_id}/snapshotpolicies:
|
||||
$ref: "./snapshotpolicy/snapshotpolicydisk.yaml"
|
||||
/snapshotpolicies/{snapshotpolicy_id}/disks:
|
||||
$ref: "./snapshotpolicy/snapshotpolicydisk2.yaml"
|
||||
/disks/{disk_id}/snapshotpolicies/{snapshotpolicy_id}:
|
||||
$ref: "./snapshotpolicy/snapshotpolicydisk3.yaml"
|
||||
/snapshotpolicies/{snapshotpolicyId}/bind-disks:
|
||||
$ref: "./snapshotpolicy/bind-disk.yaml"
|
||||
/snapshotpolicies/{snapshotpolicyId}/unbind-disks:
|
||||
$ref: "./snapshotpolicy/unbind-disk.yaml"
|
||||
|
||||
/loadbalancers:
|
||||
$ref: "./loadbalancer/loadbalancers.yaml"
|
||||
/loadbalancers/{loadbalancerId}:
|
||||
|
||||
28
docs/parameters/snapshotpolicy.yaml
Normal file
28
docs/parameters/snapshotpolicy.yaml
Normal file
@@ -0,0 +1,28 @@
|
||||
snapshotpolicyId:
|
||||
name: snapshotpolicyId
|
||||
required: true
|
||||
in: path
|
||||
description: 自动快照策略的ID
|
||||
diskId:
|
||||
name: diskId
|
||||
in: path
|
||||
description: 磁盘的ID
|
||||
retention_days:
|
||||
name: retention_days
|
||||
in: query
|
||||
type: integer
|
||||
description: 快照的保存时间(永久保存选-1)
|
||||
repeat_weekdays:
|
||||
name: repeat_weekdays
|
||||
in: query
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
description: 做快照的时间(周几)
|
||||
time_points:
|
||||
name: time_points
|
||||
in: query
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
description: 做快照的时间(每天几点)
|
||||
189
docs/schemas/snapshotpolicy.yaml
Normal file
189
docs/schemas/snapshotpolicy.yaml
Normal file
@@ -0,0 +1,189 @@
|
||||
CanDelete:
|
||||
type: string
|
||||
example: true
|
||||
description: 可否删除
|
||||
CanUpdate:
|
||||
type: string
|
||||
example: false
|
||||
description: 可否更新
|
||||
CreatedAt:
|
||||
type: string
|
||||
example: 2019-05-30T08:46:12.000000Z
|
||||
description: 资源创建时间
|
||||
UpdatedAt:
|
||||
type: string
|
||||
example: 2019-05-30T08:46:12.000000Z
|
||||
description: 资源最近一次更新时间
|
||||
|
||||
SnapshotPolicy:
|
||||
type: object
|
||||
description: 自动快照策略
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
example: ea27c0ce-5870-49f3-8d57-f53e63f40361
|
||||
description: 自动快照策略ID
|
||||
readOnly: true
|
||||
name:
|
||||
type: string
|
||||
description: 自动快照策略名称
|
||||
example: snapshotpolicy-jo5pskhg
|
||||
retention_days:
|
||||
type: integer
|
||||
example: 10
|
||||
description: 快照保存的时间(-1为永久保存)
|
||||
repeat_weekdays:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
example: [1, 2]
|
||||
description: 做快照的时间(每周的周几)
|
||||
time_points:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
example: [2]
|
||||
description: 做快照的时间(每天的几点)
|
||||
is_activated:
|
||||
type: boolean
|
||||
example: true
|
||||
description: 是否启用快照策略
|
||||
binding_disk_count:
|
||||
type: integer
|
||||
example: 3
|
||||
description: 自动快照策略绑定的磁盘数量
|
||||
can_delete:
|
||||
$ref: '#/CanDelete'
|
||||
can_update:
|
||||
$ref: '#/CanUpdate'
|
||||
created_at:
|
||||
$ref: '#/CreatedAt'
|
||||
updated_at:
|
||||
$ref: '#/UpdatedAt'
|
||||
is_emulated:
|
||||
type: boolean
|
||||
example: false
|
||||
description: 是否是虚拟出来的实例
|
||||
status:
|
||||
type: string
|
||||
example: init
|
||||
description: 状态
|
||||
update_version:
|
||||
type: integer
|
||||
example: 2
|
||||
description: 资源被更新的次数
|
||||
|
||||
SnapshotPolicyCreate:
|
||||
type: object
|
||||
properties:
|
||||
snapshotpolicy:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
- retention_days
|
||||
- repeat_weekdays
|
||||
- time_points
|
||||
- is_activated
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: snapshotpolicy-jo5pskhg
|
||||
description: 自动快照策略名称
|
||||
retention_days:
|
||||
type: integer
|
||||
example: 10
|
||||
description: 快照保存的时间(-1为永久保存)
|
||||
repeat_weekdays:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
example: [1, 2]
|
||||
description: 做快照的时间(每周的周几)
|
||||
time_points:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
example: [2]
|
||||
description: 做快照的时间(每天的几点)
|
||||
is_activated:
|
||||
type: boolean
|
||||
example: true
|
||||
description: 是否启用快照策略
|
||||
|
||||
SnapshotPolicyListResponse:
|
||||
type: object
|
||||
properties:
|
||||
limit:
|
||||
type: integer
|
||||
example: 20
|
||||
total:
|
||||
type: integer
|
||||
example: 12
|
||||
snapshotpolicies:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/SnapshotPolicy'
|
||||
|
||||
|
||||
SnapshotPolicyResponse:
|
||||
type: object
|
||||
properties:
|
||||
snapshotpolicy:
|
||||
type: object
|
||||
$ref: '#/SnapshotPolicy'
|
||||
|
||||
SnapshotPolicyDisk:
|
||||
type: object
|
||||
properties:
|
||||
can_delete:
|
||||
$ref: '#/CanDelete'
|
||||
can_update:
|
||||
$ref: '#/CanUpdate'
|
||||
created_at:
|
||||
$ref: '#/CreatedAt'
|
||||
updated_at:
|
||||
$ref: '#/UpdatedAt'
|
||||
status:
|
||||
type: string
|
||||
example: init
|
||||
description: 状态
|
||||
snapshotpolicy_id:
|
||||
type: string
|
||||
example: -be8b-4f0f-8885-797930266c6539210785
|
||||
description: 自动快照策略ID
|
||||
disk_id:
|
||||
type: string
|
||||
example: f7749379-34b1-4219-8835-257615cf34f6
|
||||
description: 磁盘ID
|
||||
|
||||
SnapshotPolicyDiskResponse:
|
||||
type: object
|
||||
properties:
|
||||
snapshotpolicydisk:
|
||||
type: object
|
||||
$ref: '#/SnapshotPolicyDisk'
|
||||
|
||||
SnapshotPolicyDiskListResponse:
|
||||
type: object
|
||||
properties:
|
||||
total:
|
||||
type: integer
|
||||
example: 20
|
||||
snapshotpolicydisks:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/SnapshotPolicyDisk'
|
||||
|
||||
SnapshotPolicyBindDisk:
|
||||
type: object
|
||||
required:
|
||||
- disk.0
|
||||
properties:
|
||||
disk.0:
|
||||
type: string
|
||||
example: vv100455-79ef-43a3-8fc3-23adc74b8b87
|
||||
description: 待绑定的disk的ID
|
||||
disk.1:
|
||||
type: string
|
||||
example: dd100399-79ef-43a3-8fc3-23adc74b8b87
|
||||
description: 待绑定的disk的ID
|
||||
16
docs/snapshotpolicy/bind-disk.yaml
Normal file
16
docs/snapshotpolicy/bind-disk.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
post:
|
||||
summary: 批量绑定磁盘
|
||||
parameters:
|
||||
- $ref: '../parameters/snapshotpolicy.yaml#/snapshotpolicyId'
|
||||
- in: body
|
||||
name: disks
|
||||
required: true
|
||||
schema:
|
||||
$ref: '../schemas/snapshotpolicy.yaml#/SnapshotPolicyBindDisk'
|
||||
responses:
|
||||
200:
|
||||
description: 自动快照策略
|
||||
schema:
|
||||
$ref: '../schemas/snapshotpolicy.yaml#/SnapshotPolicyResponse'
|
||||
tags:
|
||||
- snapshotpolicy
|
||||
32
docs/snapshotpolicy/snapshotpolicies.yaml
Normal file
32
docs/snapshotpolicy/snapshotpolicies.yaml
Normal file
@@ -0,0 +1,32 @@
|
||||
get:
|
||||
summary: 按指定条件列出快照策略
|
||||
parameters:
|
||||
- $ref: "../parameters/common.yaml#/offset"
|
||||
- $ref: "../parameters/common.yaml#/limit"
|
||||
- $ref: "../parameters/snapshotpolicy.yaml#/retention_days"
|
||||
- $ref: "../parameters/snapshotpolicy.yaml#/repeat_weekdays"
|
||||
- $ref: "../parameters/snapshotpolicy.yaml#/time_points"
|
||||
|
||||
responses:
|
||||
200:
|
||||
description: 快照策略列表信息
|
||||
schema:
|
||||
$ref: "../schemas/snapshotpolicy.yaml#/SnapshotPolicyListResponse"
|
||||
tags:
|
||||
- snapshotpolicy
|
||||
|
||||
post:
|
||||
summary: 创建自动快照策略
|
||||
parameters:
|
||||
- in: body
|
||||
name: snapshotpolicy
|
||||
required: true
|
||||
schema:
|
||||
$ref: '../schemas/snapshotpolicy.yaml#/SnapshotPolicyCreate'
|
||||
responses:
|
||||
200:
|
||||
description: 新建自动快照策略的信息
|
||||
schema:
|
||||
$ref: '../schemas/snapshotpolicy.yaml#/SnapshotPolicyResponse'
|
||||
tags:
|
||||
- snapshotpolicy
|
||||
22
docs/snapshotpolicy/snapshotpolicy.yaml
Normal file
22
docs/snapshotpolicy/snapshotpolicy.yaml
Normal file
@@ -0,0 +1,22 @@
|
||||
get:
|
||||
summary: 获取指定自动快照策略信息
|
||||
parameters:
|
||||
- $ref: "../parameters/snapshotpolicy.yaml#/snapshotpolicyId"
|
||||
responses:
|
||||
200:
|
||||
description: 自动快照策略信息
|
||||
schema:
|
||||
$ref: "../schemas/snapshotpolicy.yaml#/SnapshotPolicyResponse"
|
||||
tags:
|
||||
- snapshotpolicy
|
||||
|
||||
delete:
|
||||
summary: 删除指定自动快照
|
||||
parameters:
|
||||
- $ref: '../parameters/snapshotpolicy.yaml#/snapshotpolicyId'
|
||||
responses:
|
||||
200:
|
||||
schema:
|
||||
$ref: '../schemas/snapshotpolicy.yaml#/SnapshotPolicyResponse'
|
||||
tags:
|
||||
- snapshotpolicy
|
||||
11
docs/snapshotpolicy/snapshotpolicydisk.yaml
Normal file
11
docs/snapshotpolicy/snapshotpolicydisk.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
get:
|
||||
summary: 列出指定磁盘下所有绑定的自动快照策略
|
||||
parameters:
|
||||
- $ref: '../parameters/snapshotpolicy.yaml#/diskId'
|
||||
responses:
|
||||
200:
|
||||
description: 自动快照策略ID列表
|
||||
schema:
|
||||
$ref: '../schemas/snapshotpolicy.yaml#/SnapshotPolicyDiskListResponse'
|
||||
tags:
|
||||
- snapshotpolicy
|
||||
11
docs/snapshotpolicy/snapshotpolicydisk2.yaml
Normal file
11
docs/snapshotpolicy/snapshotpolicydisk2.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
get:
|
||||
summary: 列出指定自动快照策略所有绑定的磁盘
|
||||
parameters:
|
||||
- $ref: '../parameters/snapshotpolicy.yaml#/snapshotpolicyId'
|
||||
responses:
|
||||
200:
|
||||
description: 自动快照策略ID列表
|
||||
schema:
|
||||
$ref: '../schemas/snapshotpolicy.yaml#/SnapshotPolicyDiskListResponse'
|
||||
tags:
|
||||
- snapshotpolicy
|
||||
23
docs/snapshotpolicy/snapshotpolicydisk3.yaml
Normal file
23
docs/snapshotpolicy/snapshotpolicydisk3.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
post:
|
||||
summary: 绑定指定磁盘和自动快照策略
|
||||
parameters:
|
||||
- $ref: '../parameters/snapshotpolicy.yaml#/diskId'
|
||||
- $ref: '../parameters/snapshotpolicy.yaml#/snapshotpolicyId'
|
||||
responses:
|
||||
200:
|
||||
schema:
|
||||
$ref: '../schemas/snapshotpolicy.yaml#/SnapshotPolicyDiskResponse'
|
||||
tags:
|
||||
- snapshotpolicy
|
||||
|
||||
delete:
|
||||
summary: 解绑指定磁盘和自动快照策略
|
||||
parameters:
|
||||
- $ref: '../parameters/snapshotpolicy.yaml#/diskId'
|
||||
- $ref: '../parameters/snapshotpolicy.yaml#/snapshotpolicyId'
|
||||
responses:
|
||||
200:
|
||||
schema:
|
||||
$ref: '../schemas/snapshotpolicy.yaml#/SnapshotPolicyDiskResponse'
|
||||
tags:
|
||||
- snapshotpolicy
|
||||
16
docs/snapshotpolicy/unbind-disk.yaml
Normal file
16
docs/snapshotpolicy/unbind-disk.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
post:
|
||||
summary: 批量解绑磁盘
|
||||
parameters:
|
||||
- $ref: '../parameters/snapshotpolicy.yaml#/snapshotpolicyId'
|
||||
- in: body
|
||||
name: disks
|
||||
required: true
|
||||
schema:
|
||||
$ref: '../schemas/snapshotpolicy.yaml#/SnapshotPolicyBindDisk'
|
||||
responses:
|
||||
200:
|
||||
description: 自动快照策略
|
||||
schema:
|
||||
$ref: '../schemas/snapshotpolicy.yaml#/SnapshotPolicyResponse'
|
||||
tags:
|
||||
- snapshotpolicy
|
||||
@@ -41,9 +41,6 @@ type SSnapshotPolicyCreateInput struct {
|
||||
ProjectId string `json:"project_id"`
|
||||
DomainId string `json:"domain_id"`
|
||||
|
||||
ManagerId string `json:"manager_id"`
|
||||
CloudregionId string `json:"cloudregion_id"`
|
||||
|
||||
RetentionDays int `json:"retention_days"`
|
||||
RepeatWeekdays []int `json:"repeat_weekdays"`
|
||||
TimePoints []int `json:"time_points"`
|
||||
@@ -56,9 +53,6 @@ type SSnapshotPolicyCreateInternalInput struct {
|
||||
ProjectId string
|
||||
DomainId string
|
||||
|
||||
ManagerId string
|
||||
CloudregionId string
|
||||
|
||||
RetentionDays int
|
||||
RepeatWeekdays uint8
|
||||
TimePoints uint32
|
||||
|
||||
@@ -26,10 +26,20 @@ const (
|
||||
SNAPSHOT_DELETING = "deleting"
|
||||
SNAPSHOT_UNKNOWN = "unknown"
|
||||
|
||||
SNAPSHOT_POLICY_CREATING = "creating"
|
||||
SNAPSHOT_POLICY_CREATING = "creating"
|
||||
|
||||
SNAPSHOT_POLICY_READY = "ready"
|
||||
SNAPSHOT_POLICY_CREATE_FAILED = "create_failed"
|
||||
SNAPSHOT_POLICY_UPDATING = "updating"
|
||||
SNAPSHOT_POLICY_UNKNOWN = "unknown"
|
||||
SNAPSHOT_POLICY_DELETING = "deleting"
|
||||
SNAPSHOT_POLICY_DELETE_FAILED = "delete_failed"
|
||||
|
||||
SNAPSHOT_POLICY_APPLY = "applying"
|
||||
SNAPSHOT_POLICY_APPLY_FAILED = "apply_failed"
|
||||
SNAPSHOT_POLICY_CANCEL = "canceling"
|
||||
SNAPSHOT_POLICY_CANCEL_FAILED = "cancel_failed"
|
||||
|
||||
SNAPSHOT_POLICY_DISK_READY = "ready"
|
||||
SNAPSHOT_POLICY_DISK_DELETING = "deleting"
|
||||
SNAPSHOT_POLICY_DISK_DELETE_FAILED = "delete_failed"
|
||||
)
|
||||
|
||||
@@ -79,6 +79,7 @@ type ICloudRegion interface {
|
||||
GetISnapshotById(snapshotId string) (ICloudSnapshot, error)
|
||||
|
||||
CreateSnapshotPolicy(*SnapshotPolicyInput) (string, error)
|
||||
UpdateSnapshotPolicy(*SnapshotPolicyInput, string) error
|
||||
DeleteSnapshotPolicy(string) error
|
||||
ApplySnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error
|
||||
CancelSnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error
|
||||
@@ -373,7 +374,7 @@ type ICloudDisk interface {
|
||||
GetISnapshot(idStr string) (ICloudSnapshot, error)
|
||||
GetISnapshots() ([]ICloudSnapshot, error)
|
||||
|
||||
GetExtSnapshotPolicyIds() []string
|
||||
GetExtSnapshotPolicyIds() ([]string, error)
|
||||
|
||||
Resize(ctx context.Context, newSizeMB int64) error
|
||||
Reset(ctx context.Context, snapshotId string) (string, error)
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/util/fileutils"
|
||||
@@ -340,6 +341,14 @@ func (self *SDisk) GetRuningGuestCount() (int, error) {
|
||||
Filter(sqlchemy.Equals(guests.Field("status"), api.VM_RUNNING)).CountWithError()
|
||||
}
|
||||
|
||||
func (self *SDisk) DetachAfterDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
err := SnapshotPolicyDiskManager.SyncDetachByDisk(ctx, userCred, nil, self)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "detach after delete failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SDisk) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
input := new(api.DiskCreateInput)
|
||||
if err := data.Unmarshal(input); err != nil {
|
||||
@@ -1191,7 +1200,11 @@ func (self *SDisk) syncRemoveCloudDisk(ctx context.Context, userCred mcclient.To
|
||||
self.SetStatus(userCred, api.DISK_UNKNOWN, "missing original disk after sync")
|
||||
return err
|
||||
}
|
||||
// todo detach joint modle about snapshotpolicy and disk
|
||||
// detach joint modle aboutsnapshotpolicy and disk
|
||||
err = SnapshotPolicyDiskManager.SyncDetachByDisk(ctx, userCred, nil, self)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return self.RealDelete(ctx, userCred)
|
||||
}
|
||||
|
||||
@@ -1238,8 +1251,6 @@ func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.Toke
|
||||
self.CreatedAt = createdAt
|
||||
}
|
||||
|
||||
// todo sync disk's snapshotpolicy
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -1247,6 +1258,15 @@ func (self *SDisk) syncWithCloudDisk(ctx context.Context, userCred mcclient.Toke
|
||||
return err
|
||||
}
|
||||
|
||||
// sync disk's snapshotpolicy
|
||||
snapshotpolicies, err := extDisk.GetExtSnapshotPolicyIds()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Get snapshot policies of ICloudDisk %s.", extDisk.GetId())
|
||||
}
|
||||
err = SnapshotPolicyDiskManager.SyncByDisk(ctx, userCred, snapshotpolicies, syncOwnerId, self, storage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
db.OpsLog.LogSyncUpdate(self, diff, userCred)
|
||||
|
||||
SyncCloudProject(userCred, self, syncOwnerId, extDisk, storage.ManagerId)
|
||||
@@ -1287,14 +1307,22 @@ func (manager *SDiskManager) newFromCloudDisk(ctx context.Context, userCred mccl
|
||||
disk.CreatedAt = createAt
|
||||
}
|
||||
|
||||
// todo create new joint model about snapshotpolicy and disk
|
||||
|
||||
err = manager.TableSpec().Insert(&disk)
|
||||
if err != nil {
|
||||
log.Errorf("newFromCloudZone fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// create new joint model aboutsnapshotpolicy and disk
|
||||
snapshotpolicies, err := extDisk.GetExtSnapshotPolicyIds()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Get snapshot policies of ICloudDisk %s.", extDisk.GetId())
|
||||
}
|
||||
err = SnapshotPolicyDiskManager.SyncAttachDiskExt(ctx, userCred, snapshotpolicies, syncOwnerId, &disk, storage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
SyncCloudProject(userCred, &disk, syncOwnerId, extDisk, storage.ManagerId)
|
||||
|
||||
db.OpsLog.LogEvent(&disk, db.ACT_CREATE, disk.GetShortDesc(ctx), userCred)
|
||||
@@ -1544,7 +1572,12 @@ func (self *SDisk) RealDelete(ctx context.Context, userCred mcclient.TokenCreden
|
||||
guestdisk.Detach(ctx, userCred)
|
||||
}
|
||||
}
|
||||
return self.SSharableVirtualResourceBase.Delete(ctx, userCred)
|
||||
err := self.SSharableVirtualResourceBase.Delete(ctx, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.DetachAfterDelete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (self *SDisk) AllowPerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
@@ -1587,7 +1620,9 @@ func (self *SDisk) CustomizeDelete(ctx context.Context, userCred mcclient.TokenC
|
||||
jsonutils.QueryBoolean(query, "override_pending_delete", false))
|
||||
}
|
||||
|
||||
func (self *SDisk) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict {
|
||||
func (self *SDisk) getMoreDetails(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
extra *jsonutils.JSONDict) *jsonutils.
|
||||
JSONDict {
|
||||
if cloudprovider := self.GetCloudprovider(); cloudprovider != nil {
|
||||
extra.Add(jsonutils.NewString(cloudprovider.Provider), "provider")
|
||||
}
|
||||
@@ -1623,6 +1658,39 @@ func (self *SDisk) getMoreDetails(extra *jsonutils.JSONDict) *jsonutils.JSONDict
|
||||
pendingDeletedAt := self.PendingDeletedAt.Add(time.Second * time.Duration(options.Options.PendingDeleteExpireSeconds))
|
||||
extra.Add(jsonutils.NewString(timeutils.FullIsoTime(pendingDeletedAt)), "auto_delete_at")
|
||||
}
|
||||
// the binded snapshot policy list
|
||||
sds, err := SnapshotPolicyDiskManager.FetchAllByDiskID(ctx, userCred, self.Id)
|
||||
if err != nil {
|
||||
return extra
|
||||
}
|
||||
spIds := make([]string, len(sds))
|
||||
for i := range sds {
|
||||
spIds[i] = sds[i].SnapshotpolicyId
|
||||
}
|
||||
sps, err := SnapshotPolicyManager.FetchAllByIds(spIds)
|
||||
if err != nil {
|
||||
return extra
|
||||
}
|
||||
if len(sps) == 0 {
|
||||
extra.Add(jsonutils.NewString(""), "snapshotpolicy_status")
|
||||
} else {
|
||||
extra.Add(jsonutils.NewString(sds[0].Status), "snapshotpolicy_status")
|
||||
}
|
||||
// check status
|
||||
// construction for snapshotpolicies attached to disk
|
||||
snapshotpoliciesJson := jsonutils.NewArray()
|
||||
for i := range sps {
|
||||
spsJson := jsonutils.Marshal(sps[i])
|
||||
spsDict := spsJson.(*jsonutils.JSONDict)
|
||||
repeatWeekdays := SnapshotPolicyManager.RepeatWeekdaysToIntArray(sps[i].RepeatWeekdays)
|
||||
timePoints := SnapshotPolicyManager.TimePointsToIntArray(sps[i].TimePoints)
|
||||
spsDict.Remove("repeat_weekdays")
|
||||
spsDict.Remove("time_points")
|
||||
spsDict.Add(jsonutils.Marshal(repeatWeekdays), "repeat_weekdays")
|
||||
spsDict.Add(jsonutils.Marshal(timePoints), "time_points")
|
||||
snapshotpoliciesJson.Add(spsDict)
|
||||
}
|
||||
extra.Add(snapshotpoliciesJson, "snapshotpolicies")
|
||||
return extra
|
||||
}
|
||||
|
||||
@@ -1631,12 +1699,12 @@ func (self *SDisk) GetExtraDetails(ctx context.Context, userCred mcclient.TokenC
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return self.getMoreDetails(extra), nil
|
||||
return self.getMoreDetails(ctx, userCred, extra), nil
|
||||
}
|
||||
|
||||
func (self *SDisk) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
extra := self.SSharableVirtualResourceBase.GetCustomizeColumns(ctx, userCred, query)
|
||||
return self.getMoreDetails(extra)
|
||||
return self.getMoreDetails(ctx, userCred, extra)
|
||||
}
|
||||
|
||||
func (self *SDisk) StartDiskResizeTask(ctx context.Context, userCred mcclient.TokenCredential, sizeMb int64, parentTaskId string, pendingUsage quotas.IQuota) error {
|
||||
|
||||
@@ -625,14 +625,16 @@ func (snapshot *SSnapshot) purge(ctx context.Context, userCred mcclient.TokenCre
|
||||
return snapshot.RealDelete(ctx, userCred)
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error {
|
||||
sps := make([]SSnapshotPolicy, 0)
|
||||
err := fetchByManagerId(manager, providerId, &sps)
|
||||
func (manager *SSnapshotPolicyCacheManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
providerId string) error {
|
||||
// delete snapshot policy cache belong to manager
|
||||
spCaches := make([]SSnapshotPolicyCache, 0)
|
||||
err := fetchByManagerId(SnapshotPolicyCacheManager, providerId, &spCaches)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range sps {
|
||||
err := sps[i].purge(ctx, userCred)
|
||||
for i := range spCaches {
|
||||
err := spCaches[i].purge(ctx, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -640,15 +642,19 @@ func (manager *SSnapshotPolicyManager) purgeAll(ctx context.Context, userCred mc
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sp *SSnapshotPolicy) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
lockman.LockObject(ctx, sp)
|
||||
defer lockman.ReleaseObject(ctx, sp)
|
||||
|
||||
err := sp.ValidateDeleteCondition(ctx)
|
||||
func (spc *SSnapshotPolicyCache) purge(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
lockman.LockObject(ctx, spc)
|
||||
defer lockman.LockObject(ctx, spc)
|
||||
err := spc.ValidateDeleteCondition(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return sp.RealDelete(ctx, userCred)
|
||||
return spc.RealDetele(ctx, userCred)
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error {
|
||||
// delete snapshot policy cache belong to manager
|
||||
return SnapshotPolicyCacheManager.purgeAll(ctx, userCred, providerId)
|
||||
}
|
||||
|
||||
func (manager *SStoragecacheManager) purgeAll(ctx context.Context, userCred mcclient.TokenCredential, providerId string) error {
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"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/cloudprovider"
|
||||
@@ -79,12 +78,14 @@ type IRegionDriver interface {
|
||||
ValidateCreateEipData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error)
|
||||
|
||||
// Region Driver Snapshot Policy Apis
|
||||
ValidateCreateSnapshotPolicyData(context.Context, mcclient.TokenCredential, *compute.SSnapshotPolicyCreateInput, mcclient.IIdentityProvider, *jsonutils.JSONDict) error
|
||||
RequestCreateSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *SSnapshotPolicy, task taskman.ITask) error
|
||||
RequestDeleteSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *SSnapshotPolicy, task taskman.ITask) error
|
||||
//ValidateCreateSnapshotPolicyData(context.Context, mcclient.TokenCredential, *compute.SSnapshotPolicyCreateInput, mcclient.IIdentityProvider, *jsonutils.JSONDict) error
|
||||
RequestUpdateSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *SSnapshotPolicy, input cloudprovider.SnapshotPolicyInput, task taskman.ITask) error
|
||||
RequestApplySnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, task taskman.ITask, disk *SDisk, sp *SSnapshotPolicy, data jsonutils.JSONObject) error
|
||||
RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, task taskman.ITask, disk *SDisk, sp *SSnapshotPolicy, data jsonutils.JSONObject) error
|
||||
RequestPreSnapshotPolicyApply(ctx context.Context, userCred mcclient.TokenCredential, task taskman.ITask, disk *SDisk, sp *SSnapshotPolicy, data jsonutils.JSONObject) error
|
||||
|
||||
// Region Driver Snapshot Policy joint Disk Apis
|
||||
ValidateCreateSnapshopolicyDiskData(ctx context.Context, userCred mcclient.TokenCredential, diskID string) error
|
||||
ValidateCreateSnapshopolicyDiskData(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, snapshotPolicy *SSnapshotPolicy) error
|
||||
|
||||
// Region Driver Snapshot Apis
|
||||
ValidateSnapshotDelete(ctx context.Context, snapshot *SSnapshot) error
|
||||
@@ -94,8 +95,6 @@ type IRegionDriver interface {
|
||||
SnapshotIsOutOfChain(disk *SDisk) bool
|
||||
GetDiskResetParams(snapshot *SSnapshot) *jsonutils.JSONDict
|
||||
OnDiskReset(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk, snapshot *SSnapshot, data jsonutils.JSONObject) error
|
||||
RequestApplySnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *SSnapshotPolicy, task taskman.ITask, diskId string) error
|
||||
RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *SSnapshotPolicy, task taskman.ITask, diskId string) error
|
||||
OnSnapshotDelete(ctx context.Context, snapshot *SSnapshot, task taskman.ITask, data jsonutils.JSONObject) error
|
||||
|
||||
//Nat gateway
|
||||
|
||||
@@ -17,23 +17,23 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/util/compare"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"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/db/lockman"
|
||||
"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/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/bitmap"
|
||||
"yunion.io/x/onecloud/pkg/util/validate"
|
||||
)
|
||||
|
||||
type SSnapshotPolicyManager struct {
|
||||
@@ -42,10 +42,10 @@ type SSnapshotPolicyManager struct {
|
||||
|
||||
type SSnapshotPolicy struct {
|
||||
db.SVirtualResourceBase
|
||||
db.SExternalizedResourceBase
|
||||
|
||||
SManagedResourceBase
|
||||
SCloudregionResourceBase
|
||||
//db.SExternalizedResourceBase
|
||||
//
|
||||
//SManagedResourceBase
|
||||
//SCloudregionResourceBase
|
||||
|
||||
RetentionDays int `nullable:"false" list:"user" get:"user" create:"required"`
|
||||
|
||||
@@ -70,360 +70,36 @@ func init() {
|
||||
SnapshotPolicyManager.SetVirtualObject(SnapshotPolicyManager)
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
func (manager *SSnapshotPolicyManager) ValidateListConditions(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
|
||||
input := &api.SSnapshotPolicyCreateInput{}
|
||||
err := data.Unmarshal(input)
|
||||
err := query.Unmarshal(input)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("Unmarshal input failed %s", err)
|
||||
}
|
||||
input.ProjectId = ownerId.GetProjectId()
|
||||
input.DomainId = ownerId.GetProjectDomainId()
|
||||
|
||||
err = db.NewNameValidator(manager, ownerId, input.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if query.Contains("repeat_weekdays") {
|
||||
query.Remove("repeat_weekdays")
|
||||
query.Add(jsonutils.NewInt(int64(manager.RepeatWeekdaysParseIntArray(input.RepeatWeekdays))), "repeat_weekdays")
|
||||
}
|
||||
|
||||
cloudregionV := validators.NewModelIdOrNameValidator("cloudregion", "cloudregion", ownerId)
|
||||
err = cloudregionV.Validate(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if query.Contains("time_points") {
|
||||
query.Remove("time_points")
|
||||
query.Add(jsonutils.NewInt(int64(manager.RepeatWeekdaysParseIntArray(input.RepeatWeekdays))), "time_points")
|
||||
}
|
||||
cloudregion := cloudregionV.Model.(*SCloudregion)
|
||||
input.CloudregionId = cloudregion.GetId()
|
||||
|
||||
err = cloudregion.GetDriver().ValidateCreateSnapshotPolicyData(ctx, userCred, input, ownerId, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
internalInput := manager.sSnapshotPolicyCreateInputToInternal(input)
|
||||
data = internalInput.JSON(internalInput)
|
||||
return data, nil
|
||||
return query, nil
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyManager) sSnapshotPolicyCreateInputToInternal(input *api.SSnapshotPolicyCreateInput) *api.SSnapshotPolicyCreateInternalInput {
|
||||
ret := api.SSnapshotPolicyCreateInternalInput{
|
||||
Meta: input.Meta,
|
||||
Name: input.Name,
|
||||
ProjectId: input.ProjectId,
|
||||
DomainId: input.DomainId,
|
||||
ManagerId: input.ManagerId,
|
||||
CloudregionId: input.CloudregionId,
|
||||
RetentionDays: input.RetentionDays,
|
||||
}
|
||||
|
||||
ret.RepeatWeekdays = manager.RepeatWeekdaysParseIntArray(input.RepeatWeekdays)
|
||||
ret.TimePoints = manager.TimePointsParseIntArray(input.TimePoints)
|
||||
return &ret
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyManager) sSnapshotPolicyCreateInputFromInternal(input *api.SSnapshotPolicyCreateInternalInput) *api.SSnapshotPolicyCreateInput {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
self.StartCreateSnapshotPolicy(ctx, userCred, ownerId, query, data)
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) StartCreateSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
if task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyCreateTask", self, userCred, nil, "", "", nil); err != nil {
|
||||
return err
|
||||
} else {
|
||||
task.ScheduleRun(nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
self.SetStatus(userCred, api.SNAPSHOT_POLICY_DELETING, "")
|
||||
return self.StartSnapshotPolicyDeleteTask(ctx, userCred, jsonutils.NewDict(), "")
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) StartSnapshotPolicyDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error {
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyDeleteTask", self, userCred, params, parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
ret := self.SCloudregionResourceBase.GetCustomizeColumns(ctx, userCred, query)
|
||||
ret.Update(self.SVirtualResourceBase.GetCustomizeColumns(ctx, userCred, query))
|
||||
|
||||
// more
|
||||
weekdays := SnapshotPolicyManager.RepeatWeekdaysToIntArray(self.RepeatWeekdays)
|
||||
timePoints := SnapshotPolicyManager.TimePointsToIntArray(self.TimePoints)
|
||||
ret.Add(jsonutils.Marshal(weekdays), "repeat_weekdays")
|
||||
ret.Add(jsonutils.Marshal(timePoints), "time_points")
|
||||
return ret
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
|
||||
ret := jsonutils.NewDict()
|
||||
|
||||
// more
|
||||
weekdays := SnapshotPolicyManager.RepeatWeekdaysToIntArray(self.RepeatWeekdays)
|
||||
timePoints := SnapshotPolicyManager.TimePointsToIntArray(self.TimePoints)
|
||||
ret.Add(jsonutils.Marshal(weekdays), "repeat_weekdays")
|
||||
ret.Add(jsonutils.Marshal(timePoints), "time_points")
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) GetIRegion() (cloudprovider.ICloudRegion, error) {
|
||||
provider, err := self.GetDriver()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("No cloudprovider for sp %s: %s", self.Name, err)
|
||||
}
|
||||
region := self.GetRegion()
|
||||
if region == nil {
|
||||
return nil, fmt.Errorf("failed to find region for sp %s", self.Name)
|
||||
}
|
||||
return provider.GetIRegionById(region.ExternalId)
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyManager) RepeatWeekdaysParseIntArray(nums []int) uint8 {
|
||||
return uint8(bitmap.IntArray2Uint(nums))
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyManager) RepeatWeekdaysToIntArray(n uint8) []int {
|
||||
return bitmap.Uint2IntArray(uint32(n))
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyManager) TimePointsParseIntArray(nums []int) uint32 {
|
||||
return bitmap.IntArray2Uint(nums)
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyManager) TimePointsToIntArray(n uint32) []int {
|
||||
return bitmap.Uint2IntArray(n)
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) GenerateCreateSpParams() (*cloudprovider.SnapshotPolicyInput, error) {
|
||||
intWeekdays := SnapshotPolicyManager.RepeatWeekdaysToIntArray(self.RepeatWeekdays)
|
||||
intTimePoints := SnapshotPolicyManager.TimePointsToIntArray(self.TimePoints)
|
||||
|
||||
return &cloudprovider.SnapshotPolicyInput{
|
||||
RetentionDays: self.RetentionDays,
|
||||
RepeatWeekdays: intWeekdays,
|
||||
TimePoints: intTimePoints,
|
||||
PolicyName: self.Name,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyManager) SyncSnapshotPolicies(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, region *SCloudregion, snapshots []cloudprovider.ICloudSnapshotPolicy, syncOwnerId mcclient.IIdentityProvider) compare.SyncResult {
|
||||
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, syncOwnerId))
|
||||
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, syncOwnerId))
|
||||
syncResult := compare.SyncResult{}
|
||||
dbSnapshotPolicies, err := manager.getProviderSnapshotPolicies(region, provider)
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
removed := make([]SSnapshotPolicy, 0)
|
||||
commondb := make([]SSnapshotPolicy, 0)
|
||||
commonext := make([]cloudprovider.ICloudSnapshotPolicy, 0)
|
||||
added := make([]cloudprovider.ICloudSnapshotPolicy, 0)
|
||||
|
||||
err = compare.CompareSets(dbSnapshotPolicies, snapshots, &removed, &commondb, &commonext, &added)
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
for i := 0; i < len(removed); i += 1 {
|
||||
err = removed[i].syncRemoveCloudSnapshot(ctx, userCred)
|
||||
if err != nil {
|
||||
syncResult.DeleteError(err)
|
||||
} else {
|
||||
syncResult.Delete()
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(commondb); i += 1 {
|
||||
err = commondb[i].SyncWithCloudSnapshotPolicy(ctx, userCred, commonext[i], syncOwnerId, region)
|
||||
if err != nil {
|
||||
syncResult.UpdateError(err)
|
||||
} else {
|
||||
syncMetadata(ctx, userCred, &commondb[i], commonext[i])
|
||||
syncResult.Update()
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(added); i += 1 {
|
||||
local, err := manager.newFromCloudSnapshotPolicy(ctx, userCred, added[i], region, syncOwnerId, provider)
|
||||
if err != nil {
|
||||
syncResult.AddError(err)
|
||||
} else {
|
||||
syncMetadata(ctx, userCred, local, added[i])
|
||||
syncResult.Add()
|
||||
}
|
||||
}
|
||||
return syncResult
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyManager) getProviderSnapshotPolicies(region *SCloudregion, provider *SCloudprovider) ([]SSnapshotPolicy, error) {
|
||||
if region == nil || provider == nil {
|
||||
return nil, fmt.Errorf("Region is nil or provider is nil")
|
||||
}
|
||||
snapshotPolicies := make([]SSnapshotPolicy, 0)
|
||||
q := manager.Query().Equals("cloudregion_id", region.Id).Equals("manager_id", provider.Id)
|
||||
err := db.FetchModelObjects(manager, q, &snapshotPolicies)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snapshotPolicies, nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) syncRemoveCloudSnapshot(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
lockman.LockObject(ctx, self)
|
||||
defer lockman.ReleaseObject(ctx, self)
|
||||
|
||||
err := self.ValidateDeleteCondition(ctx)
|
||||
if err != nil {
|
||||
err = self.SetStatus(userCred, api.SNAPSHOT_POLICY_UNKNOWN, "sync to delete")
|
||||
} else {
|
||||
err = self.RealDelete(ctx, userCred)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DeleteModel(ctx, userCred, self)
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) SyncWithCloudSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, ext cloudprovider.ICloudSnapshotPolicy, ownerId mcclient.IIdentityProvider, region *SCloudregion) error {
|
||||
diff, err := db.UpdateWithLock(ctx, self, func() error {
|
||||
self.Name = ext.GetName()
|
||||
self.Status = ext.GetStatus()
|
||||
self.RetentionDays = ext.GetRetentionDays()
|
||||
|
||||
arw, err := ext.GetRepeatWeekdays()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
self.RepeatWeekdays = SnapshotPolicyManager.RepeatWeekdaysParseIntArray(arw)
|
||||
|
||||
atp, err := ext.GetTimePoints()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
self.TimePoints = SnapshotPolicyManager.TimePointsParseIntArray(atp)
|
||||
return nil
|
||||
})
|
||||
db.OpsLog.LogSyncUpdate(self, diff, userCred)
|
||||
SyncCloudProject(userCred, self, ownerId, ext, self.ManagerId)
|
||||
return err
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyManager) newFromCloudSnapshotPolicy(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
ext cloudprovider.ICloudSnapshotPolicy, region *SCloudregion,
|
||||
syncOwnerId mcclient.IIdentityProvider, provider *SCloudprovider,
|
||||
) (*SSnapshotPolicy, error) {
|
||||
|
||||
snapshotPolicy := SSnapshotPolicy{}
|
||||
snapshotPolicy.SetModelManager(manager, &snapshotPolicy)
|
||||
|
||||
newName, err := db.GenerateName(manager, syncOwnerId, ext.GetName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
snapshotPolicy.Name = newName
|
||||
snapshotPolicy.Status = ext.GetStatus()
|
||||
snapshotPolicy.ExternalId = ext.GetGlobalId()
|
||||
snapshotPolicy.ManagerId = provider.Id
|
||||
snapshotPolicy.CloudregionId = region.Id
|
||||
snapshotPolicy.RetentionDays = ext.GetRetentionDays()
|
||||
arw, err := ext.GetRepeatWeekdays()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
snapshotPolicy.RepeatWeekdays = SnapshotPolicyManager.RepeatWeekdaysParseIntArray(arw)
|
||||
atp, err := ext.GetTimePoints()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
snapshotPolicy.TimePoints = SnapshotPolicyManager.TimePointsParseIntArray(atp)
|
||||
|
||||
err = manager.TableSpec().Insert(&snapshotPolicy)
|
||||
if err != nil {
|
||||
log.Errorf("newFromCloudEip fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
SyncCloudProject(userCred, &snapshotPolicy, syncOwnerId, ext, snapshotPolicy.ManagerId)
|
||||
db.OpsLog.LogEvent(&snapshotPolicy, db.ACT_CREATE, snapshotPolicy.GetShortDesc(ctx), userCred)
|
||||
return &snapshotPolicy, nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) AllowPerformApplyToDisks(ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
data jsonutils.JSONObject) bool {
|
||||
return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "apply-to-disks")
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) PerformApplyToDisks(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject,
|
||||
) (jsonutils.JSONObject, error) {
|
||||
diskIds, err := self.preCheck(ctx, userCred, query, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, self.StartApplySnapshotPolicyToDisks(ctx, userCred, diskIds)
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) StartApplySnapshotPolicyToDisks(ctx context.Context, userCred mcclient.TokenCredential, diskIds []string) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Set("disk_ids", jsonutils.Marshal(diskIds))
|
||||
if task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyApplyTask", self, userCred, params, "", "", nil); err != nil {
|
||||
return err
|
||||
} else {
|
||||
task.ScheduleRun(nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) preCheck(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject,
|
||||
) ([]string, error) {
|
||||
if self.Status != api.SNAPSHOT_POLICY_READY {
|
||||
return nil, httperrors.NewInvalidStatusError("Snapshot policy status %s can't do apply", self.Status)
|
||||
}
|
||||
jsonDiskIds, err := data.Get("disks")
|
||||
if err != nil {
|
||||
return nil, httperrors.NewMissingParameterError("disks")
|
||||
}
|
||||
ids, ok := jsonDiskIds.(*jsonutils.JSONArray)
|
||||
if !ok {
|
||||
return nil, httperrors.NewInputParameterError("disk_ids %s", jsonDiskIds)
|
||||
}
|
||||
diskIds := ids.GetStringArray()
|
||||
disks := make([]string, 0)
|
||||
err = DiskManager.Query("id").Equals("cloudregion_id", self.CloudregionId).
|
||||
Equals("manager_id", self.ManagerId).In("id", diskIds).All(&disks)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInternalServerError("Query disks error %s", err)
|
||||
}
|
||||
if len(disks) < len(diskIds) {
|
||||
notFoundDisks := make([]string, 0)
|
||||
for _, id := range diskIds {
|
||||
if !utils.IsInStringArray(id, disks) {
|
||||
notFoundDisks = append(notFoundDisks, id)
|
||||
}
|
||||
}
|
||||
return nil, httperrors.NewNotFoundError("Disks %v not found", notFoundDisks)
|
||||
}
|
||||
return diskIds, nil
|
||||
func (sp *SSnapshotPolicy) AllowUpdateItem(ctx context.Context, userCred mcclient.TokenCredential) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ==================================================== fetch ==========================================================
|
||||
func (manager *SSnapshotPolicyManager) GetSnapshotPoliciesAt(week, timePoint uint32) ([]string, error) {
|
||||
|
||||
q := manager.Query("id")
|
||||
q = q.Filter(sqlchemy.Equals(sqlchemy.AND_Val("", q.Field("repeat_weekdays"), 1<<week), 1<<week))
|
||||
q = q.Filter(sqlchemy.Equals(sqlchemy.AND_Val("", q.Field("time_points"), 1<<timePoint), 1<<timePoint))
|
||||
q = q.Equals("is_activated", true)
|
||||
q.DebugQuery()
|
||||
|
||||
sps := make([]SSnapshotPolicy, 0)
|
||||
err := q.All(&sps)
|
||||
@@ -448,3 +124,560 @@ func (manager *SSnapshotPolicyManager) FetchSnapshotPolicyById(spId string) *SSn
|
||||
}
|
||||
return sp.(*SSnapshotPolicy)
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyManager) FetchAllByIds(spIds []string) ([]SSnapshotPolicy, error) {
|
||||
if spIds == nil || len(spIds) == 0 {
|
||||
return []SSnapshotPolicy{}, nil
|
||||
}
|
||||
q := manager.Query().In("id", spIds)
|
||||
sps := make([]SSnapshotPolicy, 0, 1)
|
||||
err := db.FetchModelObjects(manager, q, &sps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sps, nil
|
||||
}
|
||||
|
||||
// ==================================================== create =========================================================
|
||||
|
||||
func (manager *SSnapshotPolicyManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
|
||||
input := &api.SSnapshotPolicyCreateInput{}
|
||||
err := data.Unmarshal(input)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("Unmarshal input failed %s", err)
|
||||
}
|
||||
input.ProjectId = ownerId.GetProjectId()
|
||||
input.DomainId = ownerId.GetProjectDomainId()
|
||||
|
||||
err = db.NewNameValidator(manager, ownerId, input.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if input.RetentionDays < -1 || input.RetentionDays == 0 || input.RetentionDays > options.Options.RetentionDaysLimit {
|
||||
return nil, httperrors.NewInputParameterError("Retention days must in 1~%d or -1", options.Options.RetentionDaysLimit)
|
||||
}
|
||||
|
||||
if len(input.RepeatWeekdays) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("repeat_weekdays")
|
||||
}
|
||||
|
||||
if len(input.RepeatWeekdays) > options.Options.RepeatWeekdaysLimit {
|
||||
return nil, httperrors.NewInputParameterError("repeat_weekdays only contains %d days at most",
|
||||
options.Options.RepeatWeekdaysLimit)
|
||||
}
|
||||
input.RepeatWeekdays, err = validate.DaysCheck(input.RepeatWeekdays, 1, 7)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError(err.Error())
|
||||
}
|
||||
|
||||
if len(input.TimePoints) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("time_points")
|
||||
}
|
||||
if len(input.TimePoints) > options.Options.TimePointsLimit {
|
||||
return nil, httperrors.NewInputParameterError("time_points only contains %d points at most", options.Options.TimePointsLimit)
|
||||
}
|
||||
input.TimePoints, err = validate.DaysCheck(input.TimePoints, 0, 23)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError(err.Error())
|
||||
}
|
||||
|
||||
internalInput := manager.sSnapshotPolicyCreateInputToInternal(input)
|
||||
data = internalInput.JSON(internalInput)
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// ==================================================== update =========================================================
|
||||
|
||||
func (self *SSnapshotPolicy) AllowPerformUpdate(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
|
||||
// no fo now
|
||||
return false
|
||||
//return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "update")
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) PerformUpdate(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
//check param
|
||||
input := &api.SSnapshotPolicyCreateInput{}
|
||||
err := data.Unmarshal(input)
|
||||
if err != nil {
|
||||
return nil, httperrors.NewInputParameterError("Unmarshel input failed %s", err)
|
||||
}
|
||||
err = self.UpdateParamCheck(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, self.StartSnapshotPolicyUpdateTask(ctx, userCred, input)
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) StartSnapshotPolicyUpdateTask(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
input *api.SSnapshotPolicyCreateInput) error {
|
||||
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.Marshal(input), "input")
|
||||
self.SetStatus(userCred, api.SNAPSHOT_POLICY_UPDATING, "")
|
||||
if task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyUpdateTask", self, userCred, params,
|
||||
"", "", nil); err == nil {
|
||||
return err
|
||||
} else {
|
||||
task.ScheduleRun(nil)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateParamCheck check if update parameters are correct and need to update
|
||||
func (self *SSnapshotPolicy) UpdateParamCheck(input *api.SSnapshotPolicyCreateInput) error {
|
||||
var err error
|
||||
updateNum := 0
|
||||
|
||||
if input.RetentionDays != 0 {
|
||||
if input.RetentionDays < -1 || input.RetentionDays > 65535 {
|
||||
return httperrors.NewInputParameterError("Retention days must in 1~65535 or -1")
|
||||
}
|
||||
if input.RetentionDays != self.RetentionDays {
|
||||
updateNum++
|
||||
}
|
||||
}
|
||||
|
||||
if input.RepeatWeekdays != nil && len(input.RepeatWeekdays) != 0 {
|
||||
input.RepeatWeekdays, err = validate.DaysCheck(input.RepeatWeekdays, 1, 7)
|
||||
if err != nil {
|
||||
return httperrors.NewInputParameterError(err.Error())
|
||||
}
|
||||
if self.RepeatWeekdays != SnapshotPolicyManager.RepeatWeekdaysParseIntArray(input.RepeatWeekdays) {
|
||||
updateNum++
|
||||
}
|
||||
}
|
||||
|
||||
if input.TimePoints != nil && len(input.TimePoints) != 0 {
|
||||
input.TimePoints, err = validate.DaysCheck(input.TimePoints, 0, 23)
|
||||
if err != nil {
|
||||
return httperrors.NewInputParameterError(err.Error())
|
||||
}
|
||||
if self.TimePoints != SnapshotPolicyManager.TimePointsParseIntArray(input.TimePoints) {
|
||||
updateNum++
|
||||
}
|
||||
}
|
||||
|
||||
if updateNum == 0 {
|
||||
return httperrors.NewInputParameterError("Do not need to update")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ==================================================== delete =========================================================
|
||||
|
||||
func (self *SSnapshotPolicy) DetachAfterDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
err := SnapshotPolicyDiskManager.SyncDetachBySnapshotpolicy(ctx, userCred, nil, self)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "detach after delete failed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.
|
||||
JSONObject, data jsonutils.JSONObject) error {
|
||||
|
||||
// check if self bind to some disks
|
||||
sds, err := SnapshotPolicyDiskManager.FetchAllBySnapshotpolicyID(ctx, userCred, self.GetId())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetch bind info failed")
|
||||
}
|
||||
if len(sds) != 0 {
|
||||
return httperrors.NewBadRequestError("Couldn't delete snapshot policy binding to disks")
|
||||
}
|
||||
self.SetStatus(userCred, api.SNAPSHOT_POLICY_DELETING, "")
|
||||
return self.StartSnapshotPolicyDeleteTask(ctx, userCred, jsonutils.NewDict(), "")
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) StartSnapshotPolicyDeleteTask(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
params *jsonutils.JSONDict, parentTaskId string) error {
|
||||
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyDeleteTask", self, userCred, params,
|
||||
parentTaskId, "", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
|
||||
ret, _ := self.getMoreDetails(ctx, userCred, query)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
|
||||
|
||||
return self.getMoreDetails(ctx, userCred, query)
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) getMoreDetails(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
|
||||
|
||||
ret := query.(*jsonutils.JSONDict)
|
||||
// more
|
||||
weekdays := SnapshotPolicyManager.RepeatWeekdaysToIntArray(self.RepeatWeekdays)
|
||||
timePoints := SnapshotPolicyManager.TimePointsToIntArray(self.TimePoints)
|
||||
ret.Add(jsonutils.Marshal(weekdays), "repeat_weekdays")
|
||||
ret.Add(jsonutils.Marshal(timePoints), "time_points")
|
||||
count, err := SnapshotPolicyDiskManager.FetchDiskCountBySPID(self.Id)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
ret.Add(jsonutils.NewInt(int64(count)), "binding_disk_count")
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// ==================================================== sync ===========================================================
|
||||
func (manager *SSnapshotPolicyManager) SyncSnapshotPolicies(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
provider *SCloudprovider, region *SCloudregion, cloudSPs []cloudprovider.ICloudSnapshotPolicy,
|
||||
syncOwnerId mcclient.IIdentityProvider) compare.SyncResult {
|
||||
|
||||
lockman.LockClass(ctx, manager, db.GetLockClassKey(manager, syncOwnerId))
|
||||
defer lockman.ReleaseClass(ctx, manager, db.GetLockClassKey(manager, syncOwnerId))
|
||||
syncResult := compare.SyncResult{}
|
||||
|
||||
// Fetch allsnapshotpolicy caches
|
||||
spCaches, err := SnapshotPolicyCacheManager.FetchAllByRegionProvider(region.GetId(), provider.GetId())
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
spIdSet, spIds := make(map[string]struct{}), make([]string, 0, 2)
|
||||
for _, spCache := range spCaches {
|
||||
if _, ok := spIdSet[spCache.SnapshotpolicyId]; !ok {
|
||||
spIds = append(spIds, spCache.SnapshotpolicyId)
|
||||
spIdSet[spCache.SnapshotpolicyId] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch allsnapshotpolicy of caches above
|
||||
snapshotPolicies, err := manager.FetchAllByIds(spIds)
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return syncResult
|
||||
}
|
||||
|
||||
// structure two sets (externalID, snapshotpolicyCache), (snapshotPolicyID, snapshotPolicy)
|
||||
spSet, spCacheSet := make(map[string]*SSnapshotPolicy), make(map[string]*SSnapshotPolicyCache)
|
||||
for i := range snapshotPolicies {
|
||||
spSet[snapshotPolicies[i].GetId()] = &snapshotPolicies[i]
|
||||
}
|
||||
for i := range spCaches {
|
||||
externalId := spCaches[i].ExternalId
|
||||
if len(externalId) != 0 {
|
||||
spCacheSet[spCaches[i].ExternalId] = &spCaches[i]
|
||||
}
|
||||
}
|
||||
|
||||
// start sync
|
||||
// add forsnapshotpolicy and cache
|
||||
// delete forsnapshotpolicy cache
|
||||
added := make([]cloudprovider.ICloudSnapshotPolicy, 0, 1)
|
||||
removed := make([]*SSnapshotPolicyCache, 0, 1)
|
||||
for _, cloudSP := range cloudSPs {
|
||||
spCache, ok := spCacheSet[cloudSP.GetGlobalId()]
|
||||
if !ok {
|
||||
added = append(added, cloudSP)
|
||||
continue
|
||||
}
|
||||
snapshotPolicy := spSet[spCache.SnapshotpolicyId]
|
||||
if !snapshotPolicy.Equals(cloudSP) {
|
||||
removed = append(removed, spCache)
|
||||
added = append(added, cloudSP)
|
||||
}
|
||||
}
|
||||
|
||||
for i := range removed {
|
||||
// changesnapshotpolicy cache
|
||||
err := removed[i].RealDetele(ctx, userCred)
|
||||
if err != nil {
|
||||
syncResult.DeleteError(err)
|
||||
}
|
||||
}
|
||||
|
||||
for i := range added {
|
||||
locol, err := manager.newFromCloudSnapshotPolicy(ctx, userCred, added[i], region, syncOwnerId, provider)
|
||||
if err != nil {
|
||||
syncResult.AddError(err)
|
||||
} else {
|
||||
syncMetadata(ctx, userCred, locol, added[i])
|
||||
syncResult.Add()
|
||||
}
|
||||
}
|
||||
return compare.SyncResult{}
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyManager) newFromCloudSnapshotPolicy(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
ext cloudprovider.ICloudSnapshotPolicy, region *SCloudregion,
|
||||
syncOwnerId mcclient.IIdentityProvider, provider *SCloudprovider,
|
||||
) (*SSnapshotPolicy, error) {
|
||||
|
||||
snapshotPolicy := SSnapshotPolicy{}
|
||||
snapshotPolicy.SetModelManager(manager, &snapshotPolicy)
|
||||
|
||||
newName, err := db.GenerateName(manager, syncOwnerId, ext.GetName())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
snapshotPolicy.Name = newName
|
||||
snapshotPolicy.Status = ext.GetStatus()
|
||||
snapshotPolicy.RetentionDays = ext.GetRetentionDays()
|
||||
arw, err := ext.GetRepeatWeekdays()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
snapshotPolicy.RepeatWeekdays = SnapshotPolicyManager.RepeatWeekdaysParseIntArray(arw)
|
||||
atp, err := ext.GetTimePoints()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
snapshotPolicy.TimePoints = SnapshotPolicyManager.TimePointsParseIntArray(atp)
|
||||
|
||||
snapshotPolicy.IsActivated = tristate.NewFromBool(ext.IsActivated())
|
||||
|
||||
err = manager.TableSpec().Insert(&snapshotPolicy)
|
||||
if err != nil {
|
||||
log.Errorf("newFromCloudEip fail %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// add cache
|
||||
_, err = SnapshotPolicyCacheManager.NewCacheWithExternalId(ctx, userCred, snapshotPolicy.GetId(),
|
||||
ext.GetGlobalId(), region.GetId(), provider.GetId())
|
||||
if err != nil {
|
||||
//snapshotpolicy has been exist so that created is successful although cache created is fail.
|
||||
// disk will be sync aftersnapshotpolicy sync, cache must be right so that this sync is fail
|
||||
log.Errorf("snapshotpolicy %s created successfully but corresponding cache created fail", snapshotPolicy.GetId())
|
||||
return nil, errors.Wrapf(err, "snapshotpolicy %s created successfully but corresponding cache created fail",
|
||||
snapshotPolicy.GetId())
|
||||
}
|
||||
|
||||
SyncCloudProject(userCred, &snapshotPolicy, syncOwnerId, ext, provider.GetId())
|
||||
|
||||
db.OpsLog.LogEvent(&snapshotPolicy, db.ACT_CREATE, snapshotPolicy.GetShortDesc(ctx), userCred)
|
||||
return &snapshotPolicy, nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) Equals(cloudSP cloudprovider.ICloudSnapshotPolicy) bool {
|
||||
rws, err := cloudSP.GetRepeatWeekdays()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
tps, err := cloudSP.GetTimePoints()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
repeatWeekdays := SnapshotPolicyManager.RepeatWeekdaysParseIntArray(rws)
|
||||
timePoints := SnapshotPolicyManager.TimePointsParseIntArray(tps)
|
||||
|
||||
return self.RetentionDays == cloudSP.GetRetentionDays() && self.RepeatWeekdays == repeatWeekdays && self.
|
||||
TimePoints == timePoints && self.IsActivated.Bool() == cloudSP.IsActivated()
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyManager) getProviderSnapshotPolicies(region *SCloudregion, provider *SCloudprovider) ([]SSnapshotPolicy, error) {
|
||||
if region == nil && provider == nil {
|
||||
return nil, fmt.Errorf("Region is nil or provider is nil")
|
||||
}
|
||||
snapshotPolicies := make([]SSnapshotPolicy, 0)
|
||||
q := manager.Query().Equals("cloudregion_id", region.Id).Equals("manager_id", provider.Id)
|
||||
err := db.FetchModelObjects(manager, q, &snapshotPolicies)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snapshotPolicies, nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) syncRemoveCloudSnapshot(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
lockman.LockObject(ctx, self)
|
||||
defer lockman.ReleaseObject(ctx, self)
|
||||
|
||||
err := self.ValidateDeleteCondition(ctx)
|
||||
if err != nil {
|
||||
err = self.SetStatus(userCred, api.SNAPSHOT_POLICY_UNKNOWN, "sync to delete")
|
||||
} else {
|
||||
err = self.RealDelete(ctx, userCred)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DeleteModel(ctx, userCred, self)
|
||||
}
|
||||
|
||||
// ==================================================== utils ==========================================================
|
||||
|
||||
func (manager *SSnapshotPolicyManager) sSnapshotPolicyCreateInputToInternal(input *api.SSnapshotPolicyCreateInput,
|
||||
) *api.SSnapshotPolicyCreateInternalInput {
|
||||
ret := api.SSnapshotPolicyCreateInternalInput{
|
||||
Meta: input.Meta,
|
||||
Name: input.Name,
|
||||
ProjectId: input.ProjectId,
|
||||
DomainId: input.DomainId,
|
||||
RetentionDays: input.RetentionDays,
|
||||
}
|
||||
|
||||
ret.RepeatWeekdays = manager.RepeatWeekdaysParseIntArray(input.RepeatWeekdays)
|
||||
ret.TimePoints = manager.TimePointsParseIntArray(input.TimePoints)
|
||||
return &ret
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyManager) sSnapshotPolicyCreateInputFromInternal(input *api.
|
||||
SSnapshotPolicyCreateInternalInput) *api.SSnapshotPolicyCreateInput {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyManager) RepeatWeekdaysParseIntArray(nums []int) uint8 {
|
||||
return uint8(bitmap.IntArray2Uint(nums))
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyManager) RepeatWeekdaysToIntArray(n uint8) []int {
|
||||
return bitmap.Uint2IntArray(uint32(n))
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyManager) TimePointsParseIntArray(nums []int) uint32 {
|
||||
return bitmap.IntArray2Uint(nums)
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyManager) TimePointsToIntArray(n uint32) []int {
|
||||
return bitmap.Uint2IntArray(n)
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) GenerateCreateSpParams() *cloudprovider.SnapshotPolicyInput {
|
||||
intWeekdays := SnapshotPolicyManager.RepeatWeekdaysToIntArray(self.RepeatWeekdays)
|
||||
intTimePoints := SnapshotPolicyManager.TimePointsToIntArray(self.TimePoints)
|
||||
|
||||
return &cloudprovider.SnapshotPolicyInput{
|
||||
RetentionDays: self.RetentionDays,
|
||||
RepeatWeekdays: intWeekdays,
|
||||
TimePoints: intTimePoints,
|
||||
PolicyName: self.Name,
|
||||
}
|
||||
}
|
||||
|
||||
// ==================================================== action =========================================================
|
||||
func (manager *SSnapshotPolicy) AllowPerformBindDisks(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject) bool {
|
||||
|
||||
return manager.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, manager, "bind-disks")
|
||||
}
|
||||
|
||||
func (sp *SSnapshotPolicy) PerformBindDisks(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
|
||||
disks := jsonutils.GetArrayOfPrefix(data, "disk")
|
||||
if len(disks) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("disk.0 disk.1 ... ")
|
||||
}
|
||||
|
||||
//database
|
||||
diskSlice := make([]*SDisk, len(disks))
|
||||
for i := range disks {
|
||||
diskId, _ := disks[i].GetString()
|
||||
disk := DiskManager.FetchDiskById(diskId)
|
||||
if disk == nil {
|
||||
return nil, httperrors.NewInputParameterError("no such disk %s", diskId)
|
||||
}
|
||||
disk.SetModelManager(DiskManager, disk)
|
||||
diskSlice[i] = disk
|
||||
}
|
||||
|
||||
taskDisk := make([]*SDisk, 0, len(diskSlice))
|
||||
taskSpd := make([]*SSnapshotPolicyDisk, 0, len(diskSlice))
|
||||
for _, disk := range diskSlice {
|
||||
spd, err := SnapshotPolicyDiskManager.newSnapshotpolicyDisk(ctx, userCred, sp, disk)
|
||||
if err == ErrExistSD {
|
||||
if spd.Status == "init" {
|
||||
taskDisk = append(taskDisk, disk)
|
||||
taskSpd = append(taskSpd, spd)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("oper for database error")
|
||||
}
|
||||
taskDisk = append(taskDisk, disk)
|
||||
taskSpd = append(taskSpd, spd)
|
||||
}
|
||||
|
||||
for i := range taskDisk {
|
||||
// field 'need_detach' is not needed, because the the subject is snapshot policy not disk
|
||||
taskdata := jsonutils.NewDict()
|
||||
taskdata.Add(jsonutils.Marshal(taskSpd[i]), "snapshotPolicyDisk")
|
||||
taskdata.Add(jsonutils.Marshal(sp), "snapshotPolicy")
|
||||
if task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyApplyTask", taskDisk[i], userCred, nil,
|
||||
"", "", nil); err != nil {
|
||||
continue
|
||||
} else {
|
||||
task.ScheduleRun(taskdata)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicy) AllowPerformUnbindDisks(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject) bool {
|
||||
|
||||
return manager.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, manager, "bind-disks")
|
||||
}
|
||||
|
||||
func (sp *SSnapshotPolicy) PerformUnbindDisks(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
|
||||
disks := jsonutils.GetArrayOfPrefix(data, "disk")
|
||||
if len(disks) == 0 {
|
||||
return nil, httperrors.NewMissingParameterError("disk.0 disk.1 ... ")
|
||||
}
|
||||
|
||||
diskSlice := make([]*SDisk, len(disks))
|
||||
for i := range disks {
|
||||
diskId, _ := disks[i].GetString()
|
||||
disk := DiskManager.FetchDiskById(diskId)
|
||||
if disk == nil {
|
||||
return nil, httperrors.NewInputParameterError("no such disk %s", diskId)
|
||||
}
|
||||
disk.SetModelManager(DiskManager, disk)
|
||||
diskSlice[i] = disk
|
||||
}
|
||||
|
||||
taskDisk := make([]*SDisk, 0, len(diskSlice))
|
||||
taskSpd := make([]*SSnapshotPolicyDisk, 0, len(diskSlice))
|
||||
for _, disk := range diskSlice {
|
||||
spd, err := SnapshotPolicyDiskManager.FetchBySnapshotPolicyDisk(sp.Id, disk.GetId())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if spd == nil {
|
||||
continue
|
||||
}
|
||||
taskSpd = append(taskSpd, spd)
|
||||
taskDisk = append(taskDisk, disk)
|
||||
}
|
||||
|
||||
for i := range taskDisk {
|
||||
taskdata := jsonutils.NewDict()
|
||||
taskdata.Add(jsonutils.NewString(sp.Id), "snapshot_policy_id")
|
||||
taskdata.Add(jsonutils.Marshal(taskSpd[i]), "snapshotPolicyDisk")
|
||||
taskSpd[i].SetStatus(userCred, api.SNAPSHOT_POLICY_DISK_DELETING, "")
|
||||
if task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyCancelTask", taskDisk[i], userCred, nil, "", "",
|
||||
nil); err != nil {
|
||||
continue
|
||||
} else {
|
||||
task.ScheduleRun(taskdata)
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
415
pkg/compute/models/snapshotpolicycache.go
Normal file
415
pkg/compute/models/snapshotpolicycache.go
Normal file
@@ -0,0 +1,415 @@
|
||||
// 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"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/appsrv"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
type SSnapshotPolicyCacheManager struct {
|
||||
db.SResourceBaseManager
|
||||
}
|
||||
|
||||
type SSnapshotPolicyCache struct {
|
||||
db.SResourceBase
|
||||
SManagedResourceBase
|
||||
|
||||
Id string `width:"128" charset:"ascii" primary:"true" list:"user"`
|
||||
SnapshotpolicyId string `width:"128" charset:"ascii" create:"required"`
|
||||
CloudregionId string `width:"128" charset:"ascii" create:"required"`
|
||||
ExternalId string `width:"256" charset:"utf8" index:"true" list:"admin" create:"admin_optional"`
|
||||
}
|
||||
|
||||
var SnapshotPolicyCacheManager *SSnapshotPolicyCacheManager
|
||||
|
||||
func init() {
|
||||
SnapshotPolicyCacheManager = &SSnapshotPolicyCacheManager{
|
||||
db.NewResourceBaseManager(
|
||||
SSnapshotPolicyCache{},
|
||||
"snapshotpolicycache_tbl",
|
||||
"snapshotpolicycache",
|
||||
"snapshotpolicycaches",
|
||||
),
|
||||
}
|
||||
SnapshotPolicyCacheManager.SetVirtualObject(SnapshotPolicyCacheManager)
|
||||
}
|
||||
|
||||
func (spc *SSnapshotPolicyCache) BeforeInsert() {
|
||||
if len(spc.Id) == 0 {
|
||||
spc.Id = stringutils.UUID4()
|
||||
}
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) FilterById(q *sqlchemy.SQuery, idStr string) *sqlchemy.SQuery {
|
||||
return q.Equals("id", idStr)
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) GetIStandaloneModelManager() db.IStandaloneModelManager {
|
||||
return spcm.GetVirtualObject().(db.IStandaloneModelManager)
|
||||
}
|
||||
|
||||
func (spc *SSnapshotPolicyCache) GetIStandaloneModel() db.IStandaloneModel {
|
||||
return spc.GetVirtualObject().(db.IStandaloneModel)
|
||||
}
|
||||
|
||||
func (spc *SSnapshotPolicyCache) ClearSchedDescCache() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
||||
q, err := spcm.SResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if defsecgroup, _ := query.GetString("snapshotpolicy"); len(defsecgroup) > 0 {
|
||||
secgroup, err := SecurityGroupManager.FetchByIdOrName(userCred, defsecgroup)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, httperrors.NewResourceNotFoundError2(SecurityGroupManager.Keyword(), defsecgroup)
|
||||
} else {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
}
|
||||
q = q.Equals("snapshotpolicy_id", secgroup.GetId())
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (spc *SSnapshotPolicyCache) GetIRegion() (cloudprovider.ICloudRegion, error) {
|
||||
provider, err := spc.GetDriver()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if region := CloudregionManager.FetchRegionById(spc.CloudregionId); region != nil {
|
||||
return provider.GetIRegionById(region.ExternalId)
|
||||
}
|
||||
return nil, fmt.Errorf("failed to find iregion for snapshotpolicycache %s: cloudregion %s manager %s", spc.Id,
|
||||
spc.CloudregionId, spc.ManagerId)
|
||||
}
|
||||
|
||||
func (spc *SSnapshotPolicyCache) GetSnapshotPolicy() (*SSnapshotPolicy, error) {
|
||||
model, err := SnapshotPolicyManager.FetchById(spc.SnapshotpolicyId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetchsnapshotpolicy by %s", spc.SnapshotpolicyId)
|
||||
}
|
||||
return model.(*SSnapshotPolicy), nil
|
||||
}
|
||||
|
||||
func (spc *SSnapshotPolicyCache) SetExternalId(userCred mcclient.TokenCredential, externalId string) error {
|
||||
diff, err := db.Update(spc, func() error {
|
||||
spc.ExternalId = externalId
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
db.OpsLog.LogEvent(spc, db.ACT_UPDATE, diff, userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (spc SSnapshotPolicyCache) GetExternalId() string {
|
||||
return spc.ExternalId
|
||||
}
|
||||
|
||||
// =============================================== detach and delete ===================================================
|
||||
|
||||
func (spc *SSnapshotPolicyCache) RealDetele(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DeleteModel(ctx, userCred, spc)
|
||||
}
|
||||
|
||||
// ================================================= new and regist ====================================================
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) NewCache(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
snapshotPolicyId, regionId, providerId string) (*SSnapshotPolicyCache, error) {
|
||||
|
||||
snapshotPolicyCache := SSnapshotPolicyCache{
|
||||
SnapshotpolicyId: snapshotPolicyId,
|
||||
CloudregionId: regionId,
|
||||
}
|
||||
snapshotPolicyCache.ManagerId = providerId
|
||||
|
||||
err := snapshotPolicyCache.CreateCloudSnapshotPolicy()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// should have lock
|
||||
if err := spcm.TableSpec().Insert(&snapshotPolicyCache); err != nil {
|
||||
return nil, errors.Wrapf(err, "insert snapshotpolicycache failed")
|
||||
}
|
||||
return &snapshotPolicyCache, nil
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) NewCacheWithExternalId(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
snapshotPolicyId, externalId, regionId, providerId string) (*SSnapshotPolicyCache, error) {
|
||||
|
||||
snapshotPolicyCache := SSnapshotPolicyCache{
|
||||
SnapshotpolicyId: snapshotPolicyId,
|
||||
CloudregionId: regionId,
|
||||
ExternalId: externalId,
|
||||
}
|
||||
snapshotPolicyCache.ManagerId = providerId
|
||||
|
||||
// should have lock
|
||||
if err := spcm.TableSpec().Insert(&snapshotPolicyCache); err != nil {
|
||||
return nil, errors.Wrapf(err, "insert snapshotpolicycache failed")
|
||||
}
|
||||
return &snapshotPolicyCache, nil
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) Register(ctx context.Context, userCred mcclient.TokenCredential, snapshotPolicyId,
|
||||
regionId string, providerId string) (*SSnapshotPolicyCache, error) {
|
||||
|
||||
// Many request about same snapshot policy with same region and provider coming will cause many same cache
|
||||
// building without lock, so we must Lock.
|
||||
lockman.LockRawObject(ctx, snapshotPolicyId, regionId+providerId)
|
||||
defer lockman.ReleaseRawObject(ctx, snapshotPolicyId, regionId+providerId)
|
||||
snapshotPolicyCache, err := spcm.FetchSnapshotPolicyCache(snapshotPolicyId, regionId, providerId)
|
||||
// error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// no cache
|
||||
if snapshotPolicyCache != nil {
|
||||
return snapshotPolicyCache, nil
|
||||
}
|
||||
|
||||
return spcm.NewCache(ctx, userCred, snapshotPolicyId, regionId, providerId)
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) RegisterWithExternalID(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
snapshotPolicyId, externalId, regionId, providerId string) (*SSnapshotPolicyCache, error) {
|
||||
|
||||
snapshotPolicyCache, err := spcm.FetchSnapshotPolicyCache(snapshotPolicyId, regionId, providerId)
|
||||
// error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// no cache
|
||||
if snapshotPolicyCache != nil {
|
||||
return snapshotPolicyCache, nil
|
||||
}
|
||||
|
||||
return spcm.NewCacheWithExternalId(ctx, userCred, snapshotPolicyId, externalId, regionId, providerId)
|
||||
}
|
||||
|
||||
// ==================================================== fetch =========================================================
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) FetchSnapshotpolicyCaheById(cacheId string) (*SSnapshotPolicyCache, error) {
|
||||
q := spcm.FilterById(spcm.Query(), cacheId)
|
||||
return spcm.fetchByQuery(q)
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) FetchSnapshotPolicyCache(snapshotPolicyId, regionId, providerId string) (*SSnapshotPolicyCache, error) {
|
||||
|
||||
q := spcm.Query()
|
||||
q.Filter(sqlchemy.AND(sqlchemy.Equals(q.Field("snapshotpolicy_id"), snapshotPolicyId),
|
||||
sqlchemy.Equals(q.Field("cloudregion_id"), regionId),
|
||||
sqlchemy.Equals(q.Field("manager_id"), providerId)))
|
||||
|
||||
return spcm.fetchByQuery(q)
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) FetchSnapshotPolicyCacheByExtId(externalId, regionId,
|
||||
providerId string) (*SSnapshotPolicyCache, error) {
|
||||
|
||||
q := spcm.Query()
|
||||
q.Filter(sqlchemy.AND(sqlchemy.Equals(q.Field("external_id"), externalId),
|
||||
sqlchemy.Equals(q.Field("cloudregion_id"), regionId),
|
||||
sqlchemy.Equals(q.Field("manager_id"), providerId)))
|
||||
|
||||
return spcm.fetchByQuery(q)
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) FetchAllByExtIds(externalIds []string, regionId,
|
||||
providerId string) ([]SSnapshotPolicyCache, error) {
|
||||
|
||||
q := spcm.Query().In("external_id", externalIds).Equals("cloudregion_id", regionId).Equals("manager_id", providerId)
|
||||
return spcm.fetchAllByQuery(q)
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) FetchAllBySnpId(snapshotPolicyId string) ([]SSnapshotPolicyCache, error) {
|
||||
|
||||
q := spcm.Query().Equals("snapshotpolicy_id", snapshotPolicyId)
|
||||
return spcm.fetchAllByQuery(q)
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) FetchAllByRegionProvider(cloudregionId,
|
||||
managerId string) ([]SSnapshotPolicyCache, error) {
|
||||
|
||||
q := spcm.Query().Equals("cloudregion_id", cloudregionId).Equals("manager_id", managerId)
|
||||
return spcm.fetchAllByQuery(q)
|
||||
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) fetchAllByQuery(q *sqlchemy.SQuery) ([]SSnapshotPolicyCache, error) {
|
||||
caches := make([]SSnapshotPolicyCache, 0, 1)
|
||||
if err := db.FetchModelObjects(spcm, q, &caches); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return caches, nil
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) fetchByQuery(q *sqlchemy.SQuery) (*SSnapshotPolicyCache, error) {
|
||||
count, err := q.CountWithError()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if count == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
snapshotPolicyCache := SSnapshotPolicyCache{}
|
||||
// if exist, only one
|
||||
q.First(&snapshotPolicyCache)
|
||||
snapshotPolicyCache.SetModelManager(spcm, &snapshotPolicyCache)
|
||||
return &snapshotPolicyCache, nil
|
||||
}
|
||||
|
||||
// ============================================== cloud operation ======================================================
|
||||
// This function should call in the task.
|
||||
|
||||
type sOperaResult struct {
|
||||
err error
|
||||
snapshotPolicyId string
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) UpdateCloudSnapshotPolicy(snapshotPolicyId string,
|
||||
input *cloudprovider.SnapshotPolicyInput) error {
|
||||
//todo maybe
|
||||
|
||||
return fmt.Errorf("Not implement")
|
||||
}
|
||||
|
||||
func (spcm *SSnapshotPolicyCacheManager) DeleteCloudSnapshotPolices(ctx context.Context,
|
||||
userCred mcclient.TokenCredential, snapshotPolicyId string) error {
|
||||
|
||||
spCaches, err := spcm.FetchAllBySnpId(snapshotPolicyId)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "fetch all snapshotPolicyCaches ofsnapshotpolicy %s failed", snapshotPolicyId)
|
||||
}
|
||||
|
||||
if len(spCaches) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
wm := appsrv.NewWorkerManager("delete-cloud-snapshotpolices", len(spCaches), 1, false)
|
||||
retChan := make(chan sOperaResult)
|
||||
|
||||
for i := range spCaches {
|
||||
spc := spCaches[i]
|
||||
wm.Run(func() {
|
||||
err := spc.DeleteCloudSnapshotPolicy()
|
||||
if err != nil {
|
||||
retChan <- sOperaResult{err, spc.GetId()}
|
||||
return
|
||||
}
|
||||
err = spc.RealDetele(ctx, userCred)
|
||||
if err != nil {
|
||||
retChan <- sOperaResult{errors.Wrap(err, "delete cache in database failed"), spc.GetId()}
|
||||
return
|
||||
}
|
||||
retChan <- sOperaResult{nil, spc.GetId()}
|
||||
}, nil, func(e error) {
|
||||
retChan <- sOperaResult{e, spc.GetId()}
|
||||
})
|
||||
}
|
||||
|
||||
failedRecord := make([]string, 0)
|
||||
for i := 0; i < len(spCaches); i++ {
|
||||
ret := <-retChan
|
||||
if ret.err != nil {
|
||||
failedRecord = append(failedRecord, fmt.Sprintf("%s failed because that %s", ret.snapshotPolicyId,
|
||||
ret.err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
if len(failedRecord) != 0 {
|
||||
return fmt.Errorf("delete: " + strings.Join(failedRecord, "; "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (spc *SSnapshotPolicyCache) CreateCloudSnapshotPolicy() error {
|
||||
// create correspondingsnapshotpolicy in cloud
|
||||
iregion, err := spc.GetIRegion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
snapshotPolicy, err := spc.GetSnapshotPolicy()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
externalId, err := iregion.CreateSnapshotPolicy(snapshotPolicy.GenerateCreateSpParams())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "createsnapshotpolicy failed")
|
||||
}
|
||||
spc.ExternalId = externalId
|
||||
|
||||
iPolicy, err := iregion.GetISnapshotPolicyById(externalId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cloudprovider.WaitStatus(iPolicy, api.SNAPSHOT_POLICY_READY, 10*time.Second, 300*time.Second)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (spc *SSnapshotPolicyCache) DeleteCloudSnapshotPolicy() error {
|
||||
if len(spc.ExternalId) > 0 {
|
||||
iregion, err := spc.GetIRegion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return iregion.DeleteSnapshotPolicy(spc.ExternalId)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (spc *SSnapshotPolicyCache) UpdateCloudSnapshotPolicy(input *cloudprovider.SnapshotPolicyInput) error {
|
||||
iregion, err := spc.GetIRegion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = iregion.UpdateSnapshotPolicy(input, spc.ExternalId)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "createsnapshotpolicy failed")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -15,14 +15,21 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
@@ -30,11 +37,11 @@ type SSnapshotPolicyDiskManager struct {
|
||||
db.SVirtualJointResourceBaseManager
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyDiskManager) GetMasterFieldName() string {
|
||||
func (m *SSnapshotPolicyDiskManager) GetMasterFieldName() string {
|
||||
return "disk_id"
|
||||
}
|
||||
|
||||
func (manager *SSnapshotPolicyDiskManager) GetSlaveFieldName() string {
|
||||
func (m *SSnapshotPolicyDiskManager) GetSlaveFieldName() string {
|
||||
return "snapshotpolicy_id"
|
||||
}
|
||||
|
||||
@@ -62,66 +69,382 @@ type SSnapshotPolicyDisk struct {
|
||||
|
||||
SnapshotpolicyId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"`
|
||||
DiskId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required" index:"true"`
|
||||
Status string `width:"36" charset:"ascii" nullable:"false" default:"init" list:"user" create:"optional"`
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyDisk) Detach(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DetachJoint(ctx, userCred, self)
|
||||
func (sd *SSnapshotPolicyDisk) SetStatus(userCred mcclient.TokenCredential, status string, reason string) error {
|
||||
if sd.Status == status {
|
||||
return nil
|
||||
}
|
||||
oldStatus := sd.Status
|
||||
_, err := db.Update(sd, func() error {
|
||||
sd.Status = status
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if userCred != nil {
|
||||
notes := fmt.Sprintf("%s=>%s", oldStatus, status)
|
||||
if len(reason) > 0 {
|
||||
notes = fmt.Sprintf("%s: %s", notes, reason)
|
||||
}
|
||||
db.OpsLog.LogEvent(sd, db.ACT_UPDATE_STATUS, notes, userCred)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyDiskManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
diskId, _ := data.GetString(self.GetMasterFieldName())
|
||||
disk := DiskManager.FetchDiskById(diskId)
|
||||
err := disk.GetStorage().GetRegion().GetDriver().ValidateCreateSnapshopolicyDiskData(ctx, userCred, diskId)
|
||||
func (self *SSnapshotPolicyDisk) GetCustomizeColumns(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
|
||||
ret, _ := self.getMoreDetails(ctx, userCred, query)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyDisk) GetExtraDetails(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
|
||||
|
||||
return self.getMoreDetails(ctx, userCred, query)
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyDisk) getMoreDetails(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject) (*jsonutils.JSONDict, error) {
|
||||
|
||||
disk := DiskManager.FetchDiskById(self.DiskId)
|
||||
ret := jsonutils.NewDict()
|
||||
ret.Add(jsonutils.Marshal(disk), "disk")
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// ==================================================== fetch ==========================================================
|
||||
|
||||
func (m *SSnapshotPolicyDiskManager) FetchBySnapshotPolicyDisk(spId, diskId string) (*SSnapshotPolicyDisk, error) {
|
||||
q := m.Query().Equals("snapshotpolicy_id", spId).Equals("disk_id", diskId)
|
||||
ret := make([]SSnapshotPolicyDisk, 0, 1)
|
||||
err := db.FetchModelObjects(m, q, &ret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
if len(ret) == 0 {
|
||||
return nil, fmt.Errorf("Not Found")
|
||||
}
|
||||
return &ret[0], nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyDiskManager) FetchAllSnapshotPolicyOfDisk(ctx context.Context, userCred mcclient.TokenCredential, diskID string) ([]SSnapshotPolicyDisk, error) {
|
||||
q := self.Query()
|
||||
q.Equals(self.GetMasterFieldName(), diskID)
|
||||
func (m *SSnapshotPolicyDiskManager) FetchAllByDiskID(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
diskID string) ([]SSnapshotPolicyDisk, error) {
|
||||
|
||||
return m.fetchAll(ctx, userCred, m.GetMasterFieldName(), diskID)
|
||||
}
|
||||
|
||||
func (m *SSnapshotPolicyDiskManager) FetchAllBySnapshotpolicyID(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
snapshotPolicyID string) ([]SSnapshotPolicyDisk, error) {
|
||||
|
||||
return m.fetchAll(ctx, userCred, m.GetSlaveFieldName(), snapshotPolicyID)
|
||||
}
|
||||
|
||||
func (m *SSnapshotPolicyDiskManager) FetchDiskCountBySPID(snapshotpolicyID string) (int, error) {
|
||||
|
||||
q := m.Query().Equals("snapshotpolicy_id", snapshotpolicyID)
|
||||
return q.CountWithError()
|
||||
}
|
||||
|
||||
func (m *SSnapshotPolicyDiskManager) fetchAll(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
fieldName string, fieldValue string) ([]SSnapshotPolicyDisk, error) {
|
||||
|
||||
q := m.Query()
|
||||
q.Equals(fieldName, fieldValue)
|
||||
ret := make([]SSnapshotPolicyDisk, 0)
|
||||
err := db.FetchModelObjects(self, q, &ret)
|
||||
err := db.FetchModelObjects(m, q, &ret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyDisk) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
diskID := self.DiskId
|
||||
model, err := DiskManager.FetchById(diskID)
|
||||
if err != nil {
|
||||
log.Errorf("Fetch disk by ID %s failed", diskID)
|
||||
// ==================================================== sync ===========================================================
|
||||
|
||||
// SyncDetachByDisk will detach all snapshot policies fo cloudRelations
|
||||
// if cloudRelations is nil, it will detach all shapshot policies which has been attached to disk.
|
||||
func (m *SSnapshotPolicyDiskManager) SyncDetachByDisk(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
cloudRelations []SSnapshotPolicyDisk, disk *SDisk) error {
|
||||
snapshotPolicyDisks := cloudRelations
|
||||
var err error
|
||||
if snapshotPolicyDisks == nil {
|
||||
snapshotPolicyDisks, err = m.FetchAllByDiskID(ctx, userCred, disk.GetId())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Fetach allsnapshotpolicy of disk %s in database", disk.GetId())
|
||||
}
|
||||
}
|
||||
disk := model.(*SDisk)
|
||||
snapshotPolicyID := self.SnapshotpolicyId
|
||||
taskData := jsonutils.NewDict()
|
||||
taskData.Add(jsonutils.NewString(snapshotPolicyID), "snapshot_policy_id")
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyApplyTask", disk, userCred, taskData, "", "", nil)
|
||||
failResult := make([]string, 0, 1)
|
||||
for i := range snapshotPolicyDisks {
|
||||
err = snapshotPolicyDisks[i].DetachByDisk(ctx, userCred, disk)
|
||||
if err != nil {
|
||||
failResult = append(failResult, snapshotPolicyDisks[i].GetId())
|
||||
}
|
||||
}
|
||||
if len(failResult) != 0 {
|
||||
errInfo := "detach failed which IDs are: "
|
||||
return errors.Error(errInfo + strings.Join(failResult, ", "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SyncDetachBySnapshotpolicy detach all sn
|
||||
func (m *SSnapshotPolicyDiskManager) SyncDetachBySnapshotpolicy(ctx context.Context,
|
||||
userCred mcclient.TokenCredential, cloudRelations []SSnapshotPolicyDisk, snapshotPolicy *SSnapshotPolicy) error {
|
||||
|
||||
snapshotPolicyDisks := cloudRelations
|
||||
var err error
|
||||
if snapshotPolicyDisks == nil {
|
||||
snapshotPolicyDisks, err = m.FetchAllBySnapshotpolicyID(ctx, userCred, snapshotPolicy.GetId())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Fetach all bysnapshotpolicy %s in database", snapshotPolicy.GetId())
|
||||
}
|
||||
}
|
||||
failResult := make([]string, 0, 1)
|
||||
for i := range snapshotPolicyDisks {
|
||||
err = snapshotPolicyDisks[i].DetachBySnapshotpolicy(ctx, userCred, snapshotPolicy)
|
||||
if err != nil {
|
||||
failResult = append(failResult, snapshotPolicyDisks[i].GetId())
|
||||
}
|
||||
}
|
||||
if len(failResult) != 0 {
|
||||
errInfo := "detach failed which IDs are "
|
||||
return errors.Error(errInfo + strings.Join(failResult, ", "))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *SSnapshotPolicyDiskManager) SyncByDisk(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
extSnapshotpolicies []string, syncOwnerID mcclient.IIdentityProvider, disk *SDisk, storage *SStorage) error {
|
||||
|
||||
sds, err := m.FetchAllByDiskID(ctx, userCred, disk.GetId())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Fetach allsnapshotpolicy of disk %s in database", disk.GetId())
|
||||
}
|
||||
|
||||
//fetch snapshotPolicy Cache to find the snapshotpolicyID corresponding to extSnapshotpolicyID
|
||||
spCaches, err := SnapshotPolicyCacheManager.FetchAllByExtIds(extSnapshotpolicies, storage.GetRegion().GetId(),
|
||||
storage.ManagerId)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "fetachsnapshotpolicy caches failed")
|
||||
}
|
||||
cloudRelationsSet := make(map[string]struct{})
|
||||
for i := range spCaches {
|
||||
cloudRelationsSet[spCaches[i].SnapshotpolicyId] = struct{}{}
|
||||
}
|
||||
|
||||
removed := make([]SSnapshotPolicyDisk, 0, 1)
|
||||
added := make([]string, 0, 1)
|
||||
for i := range sds {
|
||||
if _, ok := cloudRelationsSet[sds[i].SnapshotpolicyId]; !ok {
|
||||
removed = append(removed, sds[i])
|
||||
}
|
||||
delete(cloudRelationsSet, sds[i].SnapshotpolicyId)
|
||||
}
|
||||
for k := range cloudRelationsSet {
|
||||
added = append(added, k)
|
||||
}
|
||||
err = m.SyncDetachByDisk(ctx, userCred, removed, disk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = m.SyncAttachDisk(ctx, userCred, added, syncOwnerID, disk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *SSnapshotPolicyDiskManager) SyncAttachDisk(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
Snapshotpolicies []string, syncOwnerID mcclient.IIdentityProvider, disk *SDisk) error {
|
||||
|
||||
lockman.LockClass(ctx, m, db.GetLockClassKey(m, syncOwnerID))
|
||||
defer lockman.ReleaseClass(ctx, m, db.GetLockClassKey(m, syncOwnerID))
|
||||
|
||||
failRecord := make([]string, 0, 1)
|
||||
for _, spId := range Snapshotpolicies {
|
||||
snapshotpolicyDisk, err := db.FetchJointByIds(m, disk.GetId(), spId, jsonutils.JSONNull)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
failRecord = append(failRecord,
|
||||
fmt.Sprintf("Get SnapshotpolicyDisk whose diskid %s snapshotpolicyid %s failed",
|
||||
disk.GetId(), spId))
|
||||
continue
|
||||
}
|
||||
if snapshotpolicyDisk != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
sd := SSnapshotPolicyDisk{}
|
||||
sd.DiskId = disk.GetId()
|
||||
sd.SnapshotpolicyId = spId
|
||||
sd.Status = compute.SNAPSHOT_POLICY_DISK_READY
|
||||
err = m.TableSpec().Insert(&sd)
|
||||
if err != nil {
|
||||
failRecord = append(failRecord, fmt.Sprintf("attachsnapshotpolicy %s to disk %s failed",
|
||||
spId, disk.GetId()))
|
||||
continue
|
||||
}
|
||||
}
|
||||
if len(failRecord) == 0 {
|
||||
return nil
|
||||
}
|
||||
buf := bytes.NewBufferString("sync attach extSnapshotpolicies to disk ")
|
||||
buf.WriteString(disk.GetId())
|
||||
buf.WriteString("failed because that ")
|
||||
for i := range failRecord {
|
||||
buf.WriteString(failRecord[i])
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
buf.Truncate(buf.Len() - 2)
|
||||
return errors.Error(buf.String())
|
||||
}
|
||||
|
||||
//
|
||||
func (m *SSnapshotPolicyDiskManager) SyncAttachDiskExt(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
extSnapshotpolicies []string, syncOwnerID mcclient.IIdentityProvider, disk *SDisk, storage *SStorage) error {
|
||||
|
||||
//fetch snapshotPolicy Cache to find the snapshotpolicyID corresponding to extSnapshotpolicyID
|
||||
spCaches, err := SnapshotPolicyCacheManager.FetchAllByExtIds(extSnapshotpolicies, storage.GetRegion().GetId(),
|
||||
storage.ManagerId)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "fetachsnapshotpolicy caches failed")
|
||||
}
|
||||
|
||||
snapshotPolicie := make([]string, 0, 1)
|
||||
for i := range spCaches {
|
||||
snapshotPolicie = append(snapshotPolicie, spCaches[i].SnapshotpolicyId)
|
||||
}
|
||||
|
||||
return m.SyncAttachDisk(ctx, userCred, snapshotPolicie, syncOwnerID, disk)
|
||||
}
|
||||
|
||||
// ==================================================== detach =========================================================
|
||||
|
||||
func (sd *SSnapshotPolicyDisk) RealDetach(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DeleteModel(ctx, userCred, sd)
|
||||
}
|
||||
|
||||
func (sd *SSnapshotPolicyDisk) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sd *SSnapshotPolicyDisk) Detach(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// syncDetach should lock before
|
||||
func (sd *SSnapshotPolicyDisk) DetachByDisk(ctx context.Context, userCred mcclient.TokenCredential, disk *SDisk) error {
|
||||
snapshotPolicy := SSnapshotPolicy{}
|
||||
snapshotPolicy.Id = sd.SnapshotpolicyId
|
||||
snapshotPolicy.SetModelManager(SnapshotPolicyManager, &snapshotPolicy)
|
||||
lockman.LockJointObject(ctx, disk, &snapshotPolicy)
|
||||
defer lockman.ReleaseJointObject(ctx, disk, &snapshotPolicy)
|
||||
// todo call real Detach
|
||||
return sd.RealDetach(ctx, userCred)
|
||||
}
|
||||
|
||||
func (sd *SSnapshotPolicyDisk) DetachBySnapshotpolicy(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
snapshotPolicy *SSnapshotPolicy) error {
|
||||
|
||||
disk := SDisk{}
|
||||
disk.Id = sd.DiskId
|
||||
disk.SetModelManager(DiskManager, &disk)
|
||||
lockman.LockJointObject(ctx, &disk, snapshotPolicy)
|
||||
defer lockman.ReleaseJointObject(ctx, &disk, snapshotPolicy)
|
||||
return sd.RealDetach(ctx, userCred)
|
||||
}
|
||||
|
||||
// ==================================================== create =========================================================
|
||||
|
||||
var ErrExistSD = fmt.Errorf("snapshotpolicy disk has been exist")
|
||||
|
||||
func (self *SSnapshotPolicyDiskManager) newSnapshotpolicyDisk(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
sp *SSnapshotPolicy, disk *SDisk) (*SSnapshotPolicyDisk, error) {
|
||||
|
||||
q := self.Query().Equals("snapshotpolicy_id", sp.GetId()).Equals("disk_id", disk.GetId())
|
||||
count, err := q.CountWithError()
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
if count > 0 {
|
||||
spd := SSnapshotPolicyDisk{}
|
||||
q.First(&spd)
|
||||
spd.SetModelManager(self, &spd)
|
||||
return &spd, ErrExistSD
|
||||
}
|
||||
|
||||
spd := SSnapshotPolicyDisk{SnapshotpolicyId: sp.GetId(), DiskId: disk.GetId()}
|
||||
spd.SetModelManager(self, &spd)
|
||||
|
||||
lockman.LockJointObject(ctx, disk, sp)
|
||||
defer lockman.ReleaseJointObject(ctx, disk, sp)
|
||||
return &spd, self.TableSpec().Insert(&spd)
|
||||
|
||||
}
|
||||
func (self *SSnapshotPolicyDiskManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
diskId, _ := data.GetString(self.GetMasterFieldName())
|
||||
snapshotPolicyId, _ := data.GetString(self.GetSlaveFieldName())
|
||||
disk := DiskManager.FetchDiskById(diskId)
|
||||
snapshotPolicy := SnapshotPolicyManager.FetchSnapshotPolicyById(snapshotPolicyId)
|
||||
err := disk.GetStorage().GetRegion().GetDriver().ValidateCreateSnapshopolicyDiskData(ctx, userCred, disk, snapshotPolicy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//to control that one disk should only bind one snapshot policy
|
||||
spds, err := SnapshotPolicyDiskManager.FetchAllByDiskID(ctx, userCred, diskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(spds) > 1 {
|
||||
return nil, httperrors.NewInputParameterError("disk %s has too many snapshot policy attached", diskId)
|
||||
}
|
||||
if len(spds) == 1 {
|
||||
data.Add(jsonutils.NewString(spds[0].SnapshotpolicyId), "need_detach")
|
||||
}
|
||||
// I don't want to request to database again behind
|
||||
data.Add(jsonutils.Marshal(snapshotPolicy), "snapshotPolicy")
|
||||
data.Add(jsonutils.Marshal(disk), "disk")
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (sd *SSnapshotPolicyDisk) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.
|
||||
IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
|
||||
|
||||
taskdata := data.(*jsonutils.JSONDict)
|
||||
taskdata.Add(jsonutils.Marshal(sd), "snapshotPolicyDisk")
|
||||
disk := &SDisk{}
|
||||
data.Unmarshal(disk, "disk")
|
||||
disk.SetModelManager(DiskManager, disk)
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyApplyTask", disk, userCred, nil, "", "", nil)
|
||||
if err != nil {
|
||||
log.Errorf("SnapshotPolicyApplyTask newTask error %s", err)
|
||||
} else {
|
||||
task.ScheduleRun(nil)
|
||||
task.ScheduleRun(taskdata)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicyDisk) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
|
||||
diskID := self.DiskId
|
||||
// ==================================================== delete =========================================================
|
||||
|
||||
func (sd *SSnapshotPolicyDisk) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject,
|
||||
data jsonutils.JSONObject) error {
|
||||
diskID := sd.DiskId
|
||||
model, err := DiskManager.FetchById(diskID)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Fetch disk by ID %s failed", diskID)
|
||||
}
|
||||
disk := model.(*SDisk)
|
||||
snapshotPolicyID := self.SnapshotpolicyId
|
||||
snapshotPolicyID := sd.SnapshotpolicyId
|
||||
taskData := jsonutils.NewDict()
|
||||
taskData.Add(jsonutils.NewString(snapshotPolicyID), "snapshot_policy_id")
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyCancelTask", disk, userCred, taskData, "", "", nil)
|
||||
taskData.Add(jsonutils.Marshal(sd), "snapshotPolicyDisk")
|
||||
sd.SetStatus(userCred, compute.SNAPSHOT_POLICY_DISK_DELETING, "")
|
||||
task, err := taskman.TaskManager.NewTask(ctx, "SnapshotPolicyCancelTask", disk, userCred, nil, "", "", nil)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "SnapshotPolicyCancelTask newTask error %s", err)
|
||||
} else {
|
||||
task.ScheduleRun(nil)
|
||||
task.ScheduleRun(taskData)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -77,6 +77,11 @@ type ComputeOptions struct {
|
||||
DefaultMaxSnapshotCount int `default:"9" help:"Per Disk max snapshot count, default 9"`
|
||||
DefaultMaxManualSnapshotCount int `default:"2" help:"Per Disk max manual snapshot count, default 2"`
|
||||
|
||||
//snapshot policy options
|
||||
RetentionDaysLimit int `default:"49" help:"Days of snapshot retention, default 49 days"`
|
||||
TimePointsLimit int `default:"1" help:"time point of every days, default 1 point"`
|
||||
RepeatWeekdaysLimit int `default:"7" help:"day point of every weekday, default 7 points"`
|
||||
|
||||
// sku sync
|
||||
SyncSkusDay int `default:"1" help:"Days auto sync skus data, default 1 day"`
|
||||
SyncSkusHour int `default:"3" help:"What hour start sync skus, default 03:00"`
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -805,34 +804,21 @@ func (self *SAliyunRegionDriver) ValidateUpdateLoadbalancerListenerData(ctx cont
|
||||
return self.SManagedVirtualizationRegionDriver.ValidateUpdateLoadbalancerListenerData(ctx, userCred, data, lblis, backendGroup)
|
||||
}
|
||||
|
||||
func daysValidate(days []int, min, max int) ([]int, error) {
|
||||
if len(days) == 0 {
|
||||
return days, nil
|
||||
}
|
||||
sort.Ints(days)
|
||||
|
||||
var tmp *int
|
||||
for i := 0; i < len(days); i++ {
|
||||
if days[i] < min || days[i] > max {
|
||||
return days, fmt.Errorf("Day %d out of range", days[i])
|
||||
}
|
||||
if tmp != nil && *tmp == days[i] {
|
||||
return days, fmt.Errorf("Has repeat day %v", days)
|
||||
} else {
|
||||
tmp = &days[i]
|
||||
}
|
||||
}
|
||||
return days, nil
|
||||
}
|
||||
|
||||
func (self *SAliyunRegionDriver) ValidateCreateSnapshopolicyDiskData(ctx context.Context, userCred mcclient.TokenCredential, diskID string) error {
|
||||
ret, err := models.SnapshotPolicyDiskManager.FetchAllSnapshotPolicyOfDisk(ctx, userCred, diskID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(ret) != 0 {
|
||||
return httperrors.NewBadRequestError("One disk could't attach two snapshot policy in aliyun; please detach last one first.")
|
||||
}
|
||||
func (self *SAliyunRegionDriver) ValidateCreateSnapshopolicyDiskData(ctx context.Context,
|
||||
userCred mcclient.TokenCredential, disk *models.SDisk, snapshotPolicy *models.SSnapshotPolicy) error {
|
||||
//err := self.SManagedVirtualizationRegionDriver.ValidateCreateSnapshopolicyDiskData(ctx, userCred, disk, snapshotPolicy)
|
||||
//if err != nil {
|
||||
// return nil
|
||||
//}
|
||||
//// In Aliyun, One disk only apply one snapshot policy
|
||||
//ret, err := models.SnapshotPolicyDiskManager.FetchAllByDiskID(ctx, userCred, disk.GetId())
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
//if len(ret) != 0 {
|
||||
// return httperrors.NewBadRequestError("One disk could't attach two snapshot policy in aliyun; please detach last one first.")
|
||||
//}
|
||||
//return nil
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -17,14 +17,11 @@ package regiondrivers
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"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/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
@@ -127,41 +124,16 @@ func (self *SBaseRegionDriver) RequestDeleteLoadbalancerListenerRule(ctx context
|
||||
return fmt.Errorf("Not Implement RequestDeleteLoadbalancerListenerRule")
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) ValidateCreateSnapshotPolicyData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SSnapshotPolicyCreateInput, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) error {
|
||||
var err error
|
||||
|
||||
if len(input.RepeatWeekdays) == 0 {
|
||||
return httperrors.NewMissingParameterError("repeat_weekdays")
|
||||
}
|
||||
input.RepeatWeekdays, err = daysValidate(input.RepeatWeekdays, 1, 7)
|
||||
if err != nil {
|
||||
return httperrors.NewInputParameterError(err.Error())
|
||||
}
|
||||
|
||||
if len(input.TimePoints) == 0 {
|
||||
return httperrors.NewInputParameterError("time_points")
|
||||
}
|
||||
input.TimePoints, err = daysValidate(input.TimePoints, 0, 23)
|
||||
if err != nil {
|
||||
return httperrors.NewInputParameterError(err.Error())
|
||||
}
|
||||
return nil
|
||||
func (self *SBaseRegionDriver) RequestUpdateSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, input cloudprovider.SnapshotPolicyInput, task taskman.ITask) error {
|
||||
return fmt.Errorf("Not Implement RequestUpdateSnapshotPolicy")
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) RequestCreateSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask) error {
|
||||
return fmt.Errorf("Not Implement RequestCreateSnapshotPolicy")
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) RequestDeleteSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask) error {
|
||||
return fmt.Errorf("Not Implement RequestDeleteSnapshotPolicy")
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) RequestApplySnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask, diskId string) error {
|
||||
func (self *SBaseRegionDriver) RequestApplySnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, task taskman.ITask, disk *models.SDisk, sp *models.SSnapshotPolicy, data jsonutils.JSONObject) error {
|
||||
return fmt.Errorf("Not Implement RequestApplySnapshotPolicy")
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask, diskId string) error {
|
||||
return fmt.Errorf("Not Implement RequestApplySnapshotPolicy")
|
||||
func (self *SBaseRegionDriver) RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, task taskman.ITask, disk *models.SDisk, sp *models.SSnapshotPolicy, data jsonutils.JSONObject) error {
|
||||
return fmt.Errorf("Not Implement RequestCancelSnapshotPolicy")
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) ValidateSnapshotDelete(ctx context.Context, snapshot *models.SSnapshot) error {
|
||||
@@ -192,8 +164,9 @@ func (self *SBaseRegionDriver) OnDiskReset(ctx context.Context, userCred mcclien
|
||||
return fmt.Errorf("Not Implement OnDiskReset")
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) ValidateCreateSnapshopolicyDiskData(ctx context.Context, userCred mcclient.TokenCredential, diskID string) error {
|
||||
return fmt.Errorf("Not Implement ValidateCreateSnapshotpolicyDiskData")
|
||||
func (self *SBaseRegionDriver) ValidateCreateSnapshopolicyDiskData(ctx context.Context,
|
||||
userCred mcclient.TokenCredential, disk *models.SDisk, snapshotPolicy *models.SSnapshotPolicy) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SBaseRegionDriver) OnSnapshotDelete(ctx context.Context, snapshot *models.SSnapshot, task taskman.ITask, data jsonutils.JSONObject) error {
|
||||
|
||||
@@ -21,7 +21,6 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/onecloud/pkg/util/rand"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -30,8 +29,10 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/rand"
|
||||
)
|
||||
|
||||
type SKVMRegionDriver struct {
|
||||
@@ -774,37 +775,48 @@ func (self *SKVMRegionDriver) OnDiskReset(ctx context.Context, userCred mcclient
|
||||
return models.GetStorageDriver(storage.StorageType).OnDiskReset(ctx, userCred, disk, snapshot, data)
|
||||
}
|
||||
|
||||
func (self *SKVMRegionDriver) ValidateCreateSnapshotPolicyData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SSnapshotPolicyCreateInput, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) error {
|
||||
err := self.SBaseRegionDriver.ValidateCreateSnapshotPolicyData(ctx, userCred, input, ownerId, data)
|
||||
if err != nil {
|
||||
return err
|
||||
func (self *SKVMRegionDriver) RequestUpdateSnapshotPolicy(ctx context.Context,
|
||||
userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, input cloudprovider.SnapshotPolicyInput,
|
||||
task taskman.ITask) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SKVMRegionDriver) ValidateCreateSnapshopolicyDiskData(ctx context.Context,
|
||||
userCred mcclient.TokenCredential, disk *models.SDisk, snapshotPolicy *models.SSnapshotPolicy) error {
|
||||
|
||||
if snapshotPolicy.RetentionDays < -1 || snapshotPolicy.RetentionDays == 0 || snapshotPolicy.RetentionDays > options.Options.RetentionDaysLimit {
|
||||
return httperrors.NewInputParameterError("Retention days must in 1~%d or -1", options.Options.RetentionDaysLimit)
|
||||
}
|
||||
// TODO: To be determined
|
||||
if input.RetentionDays < -1 || input.RetentionDays == 0 || input.RetentionDays > 10 {
|
||||
return httperrors.NewInputParameterError("Retention days must in 1~10 or -1")
|
||||
|
||||
repeatWeekdays := models.SnapshotPolicyManager.RepeatWeekdaysToIntArray(snapshotPolicy.RepeatWeekdays)
|
||||
timePoints := models.SnapshotPolicyManager.TimePointsToIntArray(snapshotPolicy.TimePoints)
|
||||
|
||||
if len(repeatWeekdays) > options.Options.RepeatWeekdaysLimit {
|
||||
return httperrors.NewInputParameterError("repeat_weekdays only contains %d days at most",
|
||||
options.Options.RepeatWeekdaysLimit)
|
||||
}
|
||||
|
||||
if len(timePoints) > options.Options.TimePointsLimit {
|
||||
return httperrors.NewInputParameterError("time_points only contains %d points at most", options.Options.TimePointsLimit)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SKVMRegionDriver) RequestCreateSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask) error {
|
||||
func (self *SKVMRegionDriver) RequestApplySnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, task taskman.ITask, disk *models.SDisk, sp *models.SSnapshotPolicy, data jsonutils.JSONObject) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewString(sp.GetId()), "snapshotpolicy_id")
|
||||
return data, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SKVMRegionDriver) ValidateCreateSnapshopolicyDiskData(ctx context.Context, userCred mcclient.TokenCredential, diskID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SKVMRegionDriver) RequestApplySnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask, diskId string) error {
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SKVMRegionDriver) RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask, diskId string) error {
|
||||
func (self *SKVMRegionDriver) RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, task taskman.ITask, disk *models.SDisk, sp *models.SSnapshotPolicy, data jsonutils.JSONObject) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
return nil, nil
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewString(sp.GetId()), "snapshotpolicy_id")
|
||||
return data, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
@@ -823,3 +835,13 @@ func (self *SKVMRegionDriver) RequestBindIPToNatgateway(ctx context.Context, tas
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SKVMRegionDriver) RequestPreSnapshotPolicyApply(ctx context.Context, userCred mcclient.
|
||||
TokenCredential, task taskman.ITask, disk *models.SDisk, sp *models.SSnapshotPolicy, data jsonutils.JSONObject) error {
|
||||
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
|
||||
return data, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"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/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
@@ -1041,79 +1040,73 @@ func (self *SManagedVirtualizationRegionDriver) ValidateCreateEipData(ctx contex
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizationRegionDriver) RequestCreateSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask) error {
|
||||
func (self *SManagedVirtualizationRegionDriver) RequestUpdateSnapshotPolicy(ctx context.Context, userCred mcclient.
|
||||
TokenCredential, sp *models.SSnapshotPolicy, input cloudprovider.SnapshotPolicyInput, task taskman.ITask) error {
|
||||
// it's too cumbersome to pass parameters in taskman, so change a simple way for the moment
|
||||
|
||||
//spcache, err := models.SnapshotPolicyCacheManager.FetchSnapshotPolicyCache(sp.GetId(), sp.CloudregionId, sp.ManagerId)
|
||||
//if err != nil {
|
||||
// return errors.Wrapf(err, "Fetch cache ofsnapshotpolicy %s", sp.GetId())
|
||||
//}
|
||||
//return spcache.UpdateCloudSnapshotPolicy(&input)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RequestApplySnapshotPolicy apply snapshotpolicy for public cloud.
|
||||
// In our system, one disk only can hava one snapshot policy attached.
|
||||
// Default, some public cloud such as Aliyun is same with us and this function shoule be used for these public cloud.
|
||||
// But in Some public cloud such as Qcloud different with us,
|
||||
// we should wirte a new function in corressponding regiondriver which detach all snapshotpolicy of disk after
|
||||
// attache new one.
|
||||
// You can refer to the implementations of function SQcloudRegionDriver.RequestApplySnapshotPolicy().
|
||||
func (self *SManagedVirtualizationRegionDriver) RequestApplySnapshotPolicy(ctx context.Context,
|
||||
userCred mcclient.TokenCredential, task taskman.ITask, disk *models.SDisk, sp *models.SSnapshotPolicy,
|
||||
data jsonutils.JSONObject) error {
|
||||
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
iRegion, err := sp.GetIRegion()
|
||||
|
||||
spcache, err := models.SnapshotPolicyCacheManager.Register(ctx, userCred, sp.GetId(),
|
||||
disk.GetStorage().GetRegion().GetId(),
|
||||
disk.GetStorage().ManagerId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "registersnapshotpolicy cache failed")
|
||||
}
|
||||
input, err := sp.GenerateCreateSpParams()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policyId, err := iRegion.CreateSnapshotPolicy(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = db.SetExternalId(sp, userCred, policyId)
|
||||
|
||||
iRegion, err := disk.GetIRegion()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iPolicy, err := iRegion.GetISnapshotPolicyById(policyId)
|
||||
err = iRegion.ApplySnapshotPolicyToDisks(spcache.GetExternalId(), disk.GetExternalId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = cloudprovider.WaitStatus(iPolicy, api.SNAPSHOT_POLICY_READY, 10*time.Second, 300*time.Second)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewString(sp.GetId()), "snapshotpolicy_id")
|
||||
return data, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizationRegionDriver) RequestDeleteSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
iRegion, err := sp.GetIRegion()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = iRegion.DeleteSnapshotPolicy(sp.GetExternalId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
func (self *SManagedVirtualizationRegionDriver) RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.
|
||||
TokenCredential, task taskman.ITask, disk *models.SDisk, sp *models.SSnapshotPolicy, data jsonutils.JSONObject) error {
|
||||
|
||||
func (self *SManagedVirtualizationRegionDriver) RequestApplySnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask, diskId string) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
iRegion, err := sp.GetIRegion()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = iRegion.ApplySnapshotPolicyToDisks(sp.GetExternalId(), diskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
spcache, err := models.SnapshotPolicyCacheManager.FetchSnapshotPolicyCache(sp.GetId(),
|
||||
disk.GetStorage().GetRegion().GetId(), disk.GetStorage().ManagerId)
|
||||
|
||||
func (self *SManagedVirtualizationRegionDriver) RequestCancelSnapshotPolicy(ctx context.Context, userCred mcclient.TokenCredential, sp *models.SSnapshotPolicy, task taskman.ITask, diskId string) error {
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
iRegion, err := sp.GetIRegion()
|
||||
iRegion, err := spcache.GetIRegion()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = iRegion.CancelSnapshotPolicyToDisks(sp.GetExternalId(), diskId)
|
||||
err = iRegion.CancelSnapshotPolicyToDisks(spcache.GetExternalId(), disk.GetExternalId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
data := jsonutils.NewDict()
|
||||
data.Add(jsonutils.NewString(sp.GetId()), "snapshotpolicy_id")
|
||||
return data, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
@@ -1180,7 +1173,9 @@ func (self *SManagedVirtualizationRegionDriver) GetDiskResetParams(snapshot *mod
|
||||
return params
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizationRegionDriver) OnDiskReset(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, snapshot *models.SSnapshot, data jsonutils.JSONObject) error {
|
||||
func (self *SManagedVirtualizationRegionDriver) OnDiskReset(ctx context.Context, userCred mcclient.TokenCredential,
|
||||
disk *models.SDisk, snapshot *models.SSnapshot, data jsonutils.JSONObject) error {
|
||||
|
||||
externalId, _ := data.GetString("exteranl_disk_id")
|
||||
if len(externalId) > 0 {
|
||||
_, err := db.Update(disk, func() error {
|
||||
@@ -1211,19 +1206,11 @@ func (self *SManagedVirtualizationRegionDriver) OnDiskReset(ctx context.Context,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizationRegionDriver) ValidateCreateSnapshopolicyDiskData(ctx context.Context, userCred mcclient.TokenCredential, diskID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizationRegionDriver) ValidateCreateSnapshotPolicyData(ctx context.Context, userCred mcclient.TokenCredential, input *api.SSnapshotPolicyCreateInput, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) error {
|
||||
|
||||
cloudregionV := validators.NewModelIdOrNameValidator("cloudregion", "cloudregion", ownerId)
|
||||
err := cloudregionV.Validate(data)
|
||||
if err != nil {
|
||||
return err
|
||||
func (self *SManagedVirtualizationRegionDriver) ValidateCreateSnapshopolicyDiskData(ctx context.Context,
|
||||
userCred mcclient.TokenCredential, disk *models.SDisk, snapshotPolicy *models.SSnapshotPolicy) error {
|
||||
if snapshotPolicy.RetentionDays < -1 || snapshotPolicy.RetentionDays == 0 || snapshotPolicy.RetentionDays > 65535 {
|
||||
return httperrors.NewInputParameterError("Retention days must in 1~65535 or -1")
|
||||
}
|
||||
cloudregion := cloudregionV.Model.(*models.SCloudregion)
|
||||
input.CloudregionId = cloudregion.GetId()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1243,3 +1230,13 @@ func (self *SManagedVirtualizationRegionDriver) RequestBindIPToNatgateway(ctx co
|
||||
task.ScheduleRun(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizationRegionDriver) RequestPreSnapshotPolicyApply(ctx context.Context, userCred mcclient.
|
||||
TokenCredential, task taskman.ITask, disk *models.SDisk, sp *models.SSnapshotPolicy, data jsonutils.JSONObject) error {
|
||||
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
|
||||
return data, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -743,3 +742,27 @@ func (self *SQcloudRegionDriver) ValidateCreateLoadbalancerBackendData(ctx conte
|
||||
data.Set("cloudregion_id", jsonutils.NewString(lb.CloudregionId))
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (self *SQcloudRegionDriver) RequestPreSnapshotPolicyApply(ctx context.Context, userCred mcclient.
|
||||
TokenCredential, task taskman.ITask, disk *models.SDisk, sp *models.SSnapshotPolicy, data jsonutils.JSONObject) error {
|
||||
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
|
||||
if sp == nil {
|
||||
return data, nil
|
||||
}
|
||||
spcache, err := models.SnapshotPolicyCacheManager.FetchSnapshotPolicyCache(sp.GetId(),
|
||||
disk.GetStorage().GetRegion().GetId(), disk.GetStorage().ManagerId)
|
||||
|
||||
iRegion, err := spcache.GetIRegion()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = iRegion.CancelSnapshotPolicyToDisks(spcache.GetExternalId(), disk.GetExternalId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -118,7 +118,17 @@ func (self *DiskDeleteTask) OnMasterStorageDeleteDiskCompleteFailed(ctx context.
|
||||
}
|
||||
|
||||
func (self *DiskDeleteTask) startPendingDeleteDisk(ctx context.Context, disk *models.SDisk) {
|
||||
disk.DoPendingDelete(ctx, self.UserCred)
|
||||
err := disk.DoPendingDelete(ctx, self.UserCred)
|
||||
if err != nil {
|
||||
self.OnGuestDiskDeleteCompleteFailed(ctx, disk, jsonutils.NewString("pending delete disk failed"))
|
||||
return
|
||||
}
|
||||
err = models.SnapshotPolicyDiskManager.SyncDetachByDisk(ctx, self.UserCred, nil, disk)
|
||||
if err != nil {
|
||||
self.OnGuestDiskDeleteCompleteFailed(ctx, disk,
|
||||
jsonutils.NewString("detach all snapshotpolicies of disk failed"))
|
||||
return
|
||||
}
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@ package tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
|
||||
@@ -45,15 +45,12 @@ func (self *SnapshotPolicyDeleteTask) taskFail(ctx context.Context, sp *models.S
|
||||
|
||||
func (self *SnapshotPolicyDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
sp := obj.(*models.SSnapshotPolicy)
|
||||
region := sp.GetRegion()
|
||||
if region == nil {
|
||||
self.taskFail(ctx, sp, fmt.Sprintf("failed to find region for sp %s", sp.Name))
|
||||
err := models.SnapshotPolicyCacheManager.DeleteCloudSnapshotPolices(ctx, self.UserCred, sp.GetId())
|
||||
if err != nil {
|
||||
self.taskFail(ctx, sp, err.Error())
|
||||
return
|
||||
}
|
||||
self.SetStage("OnSnapshotPolicyDeleteComplete", nil)
|
||||
if err := region.GetDriver().RequestDeleteSnapshotPolicy(ctx, self.GetUserCred(), sp, self); err != nil {
|
||||
self.taskFail(ctx, sp, err.Error())
|
||||
}
|
||||
self.OnSnapshotPolicyDeleteComplete(ctx, sp, data)
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyDeleteTask) OnSnapshotPolicyDeleteComplete(ctx context.Context, sp *models.SSnapshotPolicy, data jsonutils.JSONObject) {
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
// 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 tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"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/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
type SnapshotPolicyCreateTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(SnapshotPolicyCreateTask{})
|
||||
taskman.RegisterTask(SnapshotPolicyApplyTask{})
|
||||
taskman.RegisterTask(SnapshotPolicyCancelTask{})
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyCreateTask) taskFail(ctx context.Context, sp *models.SSnapshotPolicy, reason string) {
|
||||
sp.SetStatus(self.UserCred, compute.SNAPSHOT_POLICY_CREATE_FAILED, "")
|
||||
db.OpsLog.LogEvent(sp, db.ACT_ALLOCATE_FAIL, reason, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, sp, logclient.ACT_CREATE, false, self.UserCred, false)
|
||||
notifyclient.NotifySystemError(sp.GetId(), sp.Name, compute.SNAPSHOT_POLICY_CREATE_FAILED, reason)
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
snapshotPolicy := obj.(*models.SSnapshotPolicy)
|
||||
|
||||
region := snapshotPolicy.GetRegion()
|
||||
if region == nil {
|
||||
self.taskFail(ctx, snapshotPolicy, fmt.Sprintf("failed to find region for snapshot policy %s", snapshotPolicy.Name))
|
||||
return
|
||||
}
|
||||
self.SetStage("OnSnapshotPolicyCreate", nil)
|
||||
if err := region.GetDriver().RequestCreateSnapshotPolicy(ctx, self.GetUserCred(), snapshotPolicy, self); err != nil {
|
||||
self.taskFail(ctx, snapshotPolicy, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyCreateTask) OnSnapshotPolicyCreate(
|
||||
ctx context.Context, sp *models.SSnapshotPolicy, data jsonutils.JSONObject,
|
||||
) {
|
||||
sp.SetStatus(self.UserCred, compute.SNAPSHOT_POLICY_READY, "")
|
||||
db.OpsLog.LogEvent(sp, db.ACT_ALLOCATE, sp.GetShortDesc(ctx), self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, sp, logclient.ACT_CREATE, nil, self.UserCred, true)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyCreateTask) OnSnapshotPolicyCreateFailed(
|
||||
ctx context.Context, sp *models.SSnapshotPolicy, data jsonutils.JSONObject,
|
||||
) {
|
||||
self.taskFail(ctx, sp, data.String())
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
type SnapshotPolicyApplyTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyApplyTask) taskFail(ctx context.Context, disk *models.SDisk, snapshotPolicyId, reason string) {
|
||||
jointModel, err := db.FetchJointByIds(models.SnapshotPolicyDiskManager, disk.Id, snapshotPolicyId, jsonutils.JSONNull)
|
||||
if err != nil {
|
||||
log.Errorf("Fetch SnapshotPolicy %s Disk %s joint model failed %s", disk.Id, snapshotPolicyId, reason)
|
||||
return
|
||||
}
|
||||
snapshotPolicyDisk := jointModel.(*models.SSnapshotPolicyDisk)
|
||||
err = snapshotPolicyDisk.Detach(ctx, self.UserCred)
|
||||
if err != nil {
|
||||
log.Errorf("Delete SnapshotPolicy %s Disk %s joint model failed, need to delete", self.Id, snapshotPolicyId)
|
||||
}
|
||||
|
||||
disk.SetStatus(self.UserCred, compute.DISK_APPLY_SNAPSHOT_FAIL, reason)
|
||||
db.OpsLog.LogEvent(disk, db.ACT_APPLY_SNAPSHOT_POLICY_FAILED, reason, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_APPLY_SNAPSHOT_POLICY, reason, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyApplyTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
disk := obj.(*models.SDisk)
|
||||
snapshotPolicyID, _ := self.Params.GetString("snapshot_policy_id")
|
||||
|
||||
// fetch disk model by diksID
|
||||
model, err := models.SnapshotPolicyManager.FetchById(snapshotPolicyID)
|
||||
if err != nil {
|
||||
self.taskFail(ctx, disk, snapshotPolicyID, fmt.Sprintf("failed to fetch disk by id %s: %s", snapshotPolicyID, err.Error()))
|
||||
return
|
||||
}
|
||||
snapshotPolicy := model.(*models.SSnapshotPolicy)
|
||||
|
||||
self.SetStage("OnSnapshotPolicyApply", nil)
|
||||
if err := disk.GetStorage().GetRegion().GetDriver().
|
||||
RequestApplySnapshotPolicy(ctx, self.UserCred, snapshotPolicy, self, disk.ExternalId); err != nil {
|
||||
self.taskFail(ctx, disk, snapshotPolicyID, fmt.Sprintf("faile to attach snapshot policy %s and disk %s: %s", snapshotPolicy.Id, disk.Id, err.Error()))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyApplyTask) OnSnapshotPolicyApply(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
|
||||
db.OpsLog.LogEvent(disk, db.ACT_APPLY_SNAPSHOT_POLICY, "", self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_APPLY_SNAPSHOT_POLICY, "", self.UserCred, true)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
type SnapshotPolicyCancelTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyCancelTask) taskFail(ctx context.Context, disk *models.SDisk, snapshotPolicyId, reason string) {
|
||||
jointModel, err := db.FetchJointByIds(models.SnapshotPolicyDiskManager, disk.Id, snapshotPolicyId, jsonutils.JSONNull)
|
||||
if err != nil {
|
||||
log.Errorf("Fetch SnapshotPolicy %s Disk %s joint model failed %s", disk.Id, snapshotPolicyId, reason)
|
||||
return
|
||||
}
|
||||
snapshotPolicyDisk := jointModel.(*models.SSnapshotPolicyDisk)
|
||||
err = snapshotPolicyDisk.MarkUnDelete()
|
||||
if err != nil {
|
||||
log.Errorf("Mark undelete joint model snapshotPolicy %s and disk %s failes", snapshotPolicyId, disk.Id)
|
||||
}
|
||||
disk.SetStatus(self.UserCred, compute.DISK_CALCEL_SNAPSHOT_FAIL, reason)
|
||||
db.OpsLog.LogEvent(disk, db.ACT_CANCEL_SNAPSHOT_POLICY_FAILED, reason, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_CANCEL_SNAPSHOT_POLICY, reason, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyCancelTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
disk := obj.(*models.SDisk)
|
||||
snapshotPolicyID, _ := self.GetParams().GetString("snapshot_policy_id")
|
||||
|
||||
model, err := models.SnapshotPolicyManager.FetchById(snapshotPolicyID)
|
||||
if err != nil {
|
||||
self.taskFail(ctx, disk, snapshotPolicyID, fmt.Sprintf("failed to fetch disk by id %s: %s", snapshotPolicyID, err.Error()))
|
||||
return
|
||||
}
|
||||
snapshotPolicy := model.(*models.SSnapshotPolicy)
|
||||
self.SetStage("OnSnapshotPolicyCancel", nil)
|
||||
if err := disk.GetStorage().GetRegion().GetDriver().
|
||||
RequestCancelSnapshotPolicy(ctx, self.UserCred, snapshotPolicy, self, disk.ExternalId); err != nil {
|
||||
self.taskFail(ctx, disk, snapshotPolicyID, fmt.Sprintf("faile to detach snapshot policy %s and disk %s: %s", snapshotPolicy.Id, disk.Id, err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyCancelTask) OnSnapshotPolicyCancel(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
|
||||
db.OpsLog.LogEvent(disk, db.ACT_CANCEL_SNAPSHOT_POLICY, "", self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_CANCEL_SNAPSHOT_POLICY, "", self.UserCred, true)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
210
pkg/compute/tasks/snapshotpolicy_disk_task.go
Normal file
210
pkg/compute/tasks/snapshotpolicy_disk_task.go
Normal file
@@ -0,0 +1,210 @@
|
||||
// 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 tasks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
"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/notifyclient"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/util/logclient"
|
||||
)
|
||||
|
||||
func init() {
|
||||
taskman.RegisterTask(SnapshotPolicyApplyTask{})
|
||||
taskman.RegisterTask(SnapshotPolicyCancelTask{})
|
||||
}
|
||||
|
||||
type SnapshotPolicyApplyTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyApplyTask) taskFail(ctx context.Context, disk *models.SDisk,
|
||||
spd *models.SSnapshotPolicyDisk, reason string) {
|
||||
|
||||
if spd != nil {
|
||||
err := spd.RealDetach(ctx, self.UserCred)
|
||||
if err != nil {
|
||||
log.Errorf("Delete snapshotpolicydisk %s failed, need to delete", spd.GetId())
|
||||
}
|
||||
}
|
||||
|
||||
disk.SetStatus(self.UserCred, compute.DISK_APPLY_SNAPSHOT_FAIL, reason)
|
||||
db.OpsLog.LogEvent(disk, db.ACT_APPLY_SNAPSHOT_POLICY_FAILED, reason, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_APPLY_SNAPSHOT_POLICY, reason, self.UserCred, false)
|
||||
notifyclient.NotifySystemError(disk.GetId(), disk.Name, compute.DISK_APPLY_SNAPSHOT_FAIL, reason)
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyApplyTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
disk := obj.(*models.SDisk)
|
||||
spd := models.SSnapshotPolicyDisk{}
|
||||
data.Unmarshal(&spd, "snapshotPolicy")
|
||||
|
||||
var snapshotPolicy *models.SSnapshotPolicy
|
||||
if data.Contains("need_detach") {
|
||||
snapshotPolicyID, _ := data.GetString("need_detach")
|
||||
model, err := models.SnapshotPolicyManager.FetchById(snapshotPolicyID)
|
||||
if err != nil {
|
||||
self.taskFail(ctx, disk, &spd, err.Error())
|
||||
return
|
||||
}
|
||||
snapshotPolicy = model.(*models.SSnapshotPolicy)
|
||||
}
|
||||
self.Params.Add(jsonutils.NewString(spd.GetId()), "snapshotpolicy_id")
|
||||
|
||||
self.SetStage("OnPreSnapshotPolicyApplyComplete", nil)
|
||||
// pass data to next Stage without inserting database through this way
|
||||
if err := disk.GetStorage().GetRegion().GetDriver().RequestPreSnapshotPolicyApply(ctx, self.UserCred, self, disk, snapshotPolicy,
|
||||
data); err != nil {
|
||||
|
||||
self.taskFail(ctx, disk, &spd, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyApplyTask) OnPreSnapshotPolicyApplyCompleteFailed(ctx context.Context, disk *models.SDisk,
|
||||
reason jsonutils.JSONObject) {
|
||||
|
||||
spId, _ := self.Params.GetString("snapshotpolicy_id")
|
||||
spd, err := models.SnapshotPolicyDiskManager.FetchBySnapshotPolicyDisk(spId, disk.GetId())
|
||||
if err != nil {
|
||||
self.taskFail(ctx, disk, nil, reason.String())
|
||||
return
|
||||
}
|
||||
self.taskFail(ctx, disk, spd, reason.String())
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyApplyTask) OnPreSnapshotPolicyApplyComplete(ctx context.Context, disk *models.SDisk,
|
||||
data jsonutils.JSONObject) {
|
||||
|
||||
if data.Contains("need_detach") {
|
||||
snapshotPolicyID, _ := data.GetString("need_detach")
|
||||
spd1, err := models.SnapshotPolicyDiskManager.FetchBySnapshotPolicyDisk(snapshotPolicyID, disk.GetId())
|
||||
if err != nil {
|
||||
self.taskFail(ctx, disk, spd1, err.Error())
|
||||
return
|
||||
}
|
||||
if spd1 != nil {
|
||||
spd1.RealDetach(ctx, self.UserCred)
|
||||
}
|
||||
|
||||
}
|
||||
snapshotPolicy, spd := models.SSnapshotPolicy{}, models.SSnapshotPolicyDisk{}
|
||||
data.Unmarshal(&snapshotPolicy, "snapshotPolicy")
|
||||
data.Unmarshal(&spd, "snapshotPolicyDisk")
|
||||
self.SetStage("OnSnapshotPolicyApply", nil)
|
||||
|
||||
// pass data to next Stage without inserting database through this way
|
||||
if err := disk.GetStorage().GetRegion().GetDriver().
|
||||
RequestApplySnapshotPolicy(ctx, self.UserCred, self, disk, &snapshotPolicy, data); err != nil {
|
||||
|
||||
self.taskFail(ctx, disk, &spd, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyApplyTask) OnSnapshotPolicyApplyFailed(ctx context.Context, disk *models.SDisk,
|
||||
reason jsonutils.JSONObject) {
|
||||
|
||||
spId, _ := self.Params.GetString("snapshotpolicy_id")
|
||||
spd, err := models.SnapshotPolicyDiskManager.FetchBySnapshotPolicyDisk(spId, disk.GetId())
|
||||
if err != nil {
|
||||
self.taskFail(ctx, disk, nil, reason.String())
|
||||
return
|
||||
}
|
||||
self.taskFail(ctx, disk, spd, reason.String())
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyApplyTask) OnSnapshotPolicyApply(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
|
||||
sp_id, _ := data.GetString("snapshotpolicy_id")
|
||||
spd, err := models.SnapshotPolicyDiskManager.FetchBySnapshotPolicyDisk(sp_id, disk.GetId())
|
||||
if err != nil {
|
||||
log.Errorf("Fechsnapshotpolicy disk failed")
|
||||
}
|
||||
spd.SetStatus(self.UserCred, compute.SNAPSHOT_POLICY_DISK_READY, "")
|
||||
db.OpsLog.LogEvent(disk, db.ACT_APPLY_SNAPSHOT_POLICY, "", self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_APPLY_SNAPSHOT_POLICY, "", self.UserCred, true)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
|
||||
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
type SnapshotPolicyCancelTask struct {
|
||||
taskman.STask
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyCancelTask) taskFail(ctx context.Context, disk *models.SDisk, spd *models.SSnapshotPolicyDisk, reason string) {
|
||||
if spd != nil {
|
||||
spd.SetStatus(self.UserCred, compute.SNAPSHOT_POLICY_DISK_DELETE_FAILED, "")
|
||||
}
|
||||
disk.SetStatus(self.UserCred, compute.DISK_CALCEL_SNAPSHOT_FAIL, reason)
|
||||
db.OpsLog.LogEvent(disk, db.ACT_CANCEL_SNAPSHOT_POLICY_FAILED, reason, self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_CANCEL_SNAPSHOT_POLICY, reason, self.UserCred, false)
|
||||
self.SetStageFailed(ctx, reason)
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyCancelTask) OnInit(ctx context.Context, obj db.IStandaloneModel, data jsonutils.JSONObject) {
|
||||
disk := obj.(*models.SDisk)
|
||||
snapshotPolicyID, _ := data.GetString("snapshot_policy_id")
|
||||
spd := models.SSnapshotPolicyDisk{}
|
||||
data.Unmarshal(&spd, "snapshotPolicyDisk")
|
||||
self.Params.Add(jsonutils.NewString(snapshotPolicyID), "snapshotpolicy_id")
|
||||
|
||||
model, err := models.SnapshotPolicyManager.FetchById(snapshotPolicyID)
|
||||
if err != nil {
|
||||
self.taskFail(ctx, disk, &spd, fmt.Sprintf("failed to fetch disk by id %s: %s", snapshotPolicyID, err.Error()))
|
||||
return
|
||||
}
|
||||
snapshotPolicy := model.(*models.SSnapshotPolicy)
|
||||
self.SetStage("OnSnapshotPolicyCancel", nil)
|
||||
if err := disk.GetStorage().GetRegion().GetDriver().RequestCancelSnapshotPolicy(ctx, self.UserCred, self, disk, snapshotPolicy, data); err != nil {
|
||||
|
||||
self.taskFail(ctx, disk, &spd, fmt.Sprintf("faile to detach snapshot policy %s and disk %s: %s",
|
||||
snapshotPolicy.Id, disk.Id, err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyCancelTask) OnSnapshotPolicyCancelFailed(ctx context.Context, disk *models.SDisk,
|
||||
reason jsonutils.JSONObject) {
|
||||
|
||||
spId, _ := self.Params.GetString("snapshotpolicy_id")
|
||||
spd, err := models.SnapshotPolicyDiskManager.FetchBySnapshotPolicyDisk(spId, disk.GetId())
|
||||
if err != nil {
|
||||
self.taskFail(ctx, disk, nil, reason.String())
|
||||
return
|
||||
}
|
||||
self.taskFail(ctx, disk, spd, reason.String())
|
||||
}
|
||||
|
||||
func (self *SnapshotPolicyCancelTask) OnSnapshotPolicyCancel(ctx context.Context, disk *models.SDisk, data jsonutils.JSONObject) {
|
||||
sp_id, _ := data.GetString("snapshotpolicy_id")
|
||||
spd, err := models.SnapshotPolicyDiskManager.FetchBySnapshotPolicyDisk(sp_id, disk.GetId())
|
||||
if err != nil {
|
||||
log.Errorf("Fechsnapshotpolicy disk failed")
|
||||
}
|
||||
//real detach
|
||||
spd.RealDetach(ctx, self.UserCred)
|
||||
|
||||
db.OpsLog.LogEvent(disk, db.ACT_CANCEL_SNAPSHOT_POLICY, "", self.UserCred)
|
||||
logclient.AddActionLogWithStartable(self, disk, logclient.ACT_CANCEL_SNAPSHOT_POLICY, "", self.UserCred, true)
|
||||
self.SetStageComplete(ctx, nil)
|
||||
}
|
||||
@@ -15,7 +15,8 @@
|
||||
package modules
|
||||
|
||||
var (
|
||||
SnapshotPolicyDisk JointResourceManager
|
||||
SnapshotPolicyDisk JointResourceManager
|
||||
SnapshotPolicyDisk1 JointResourceManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -27,4 +28,13 @@ func init() {
|
||||
&Disks,
|
||||
&SnapshotPoliciy)
|
||||
registerCompute(&SnapshotPolicyDisk)
|
||||
|
||||
SnapshotPolicyDisk1 = NewJointComputeManager(
|
||||
"snapshotpolicydisk",
|
||||
"snapshotpolicydisks",
|
||||
[]string{"Disk_ID", "Snapshotpolicy_ID"},
|
||||
[]string{},
|
||||
&SnapshotPoliciy,
|
||||
&Disks)
|
||||
registerCompute(&SnapshotPolicyDisk1)
|
||||
}
|
||||
|
||||
@@ -405,8 +405,11 @@ func (self *SDisk) GetCreatedAt() time.Time {
|
||||
return self.CreationTime
|
||||
}
|
||||
|
||||
func (self *SDisk) GetExtSnapshotPolicyIds() []string {
|
||||
return []string{self.AutoSnapshotPolicyId}
|
||||
func (self *SDisk) GetExtSnapshotPolicyIds() ([]string, error) {
|
||||
if len(self.AutoSnapshotPolicyId) == 0 {
|
||||
return []string{}, nil
|
||||
}
|
||||
return []string{self.AutoSnapshotPolicyId}, nil
|
||||
}
|
||||
|
||||
func (self *SDisk) GetExpiredAt() time.Time {
|
||||
|
||||
@@ -234,23 +234,17 @@ func (self *SRegion) CreateSnapshotPolicy(input *cloudprovider.SnapshotPolicyInp
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) UpdateSnapshotPolicy(
|
||||
snapshotPolicyId string, retentionDays *int,
|
||||
repeatWeekdays, timePoints *jsonutils.JSONArray, policyName string,
|
||||
) error {
|
||||
func (self *SRegion) UpdateSnapshotPolicy(input *cloudprovider.SnapshotPolicyInput, snapshotPolicyId string) error {
|
||||
params := make(map[string]string)
|
||||
params["RegionId"] = self.RegionId
|
||||
if len(policyName) > 0 {
|
||||
params["autoSnapshotPolicyName"] = policyName
|
||||
if input.RetentionDays != 0 {
|
||||
params["retentionDays"] = strconv.Itoa(input.RetentionDays)
|
||||
}
|
||||
if retentionDays != nil {
|
||||
params["retentionDays"] = strconv.Itoa(*retentionDays)
|
||||
if input.RepeatWeekdays != nil && len(input.RepeatWeekdays) != 0 {
|
||||
params["repeatWeekdays"] = jsonutils.Marshal(input.GetStringArrayRepeatWeekdays()).String()
|
||||
}
|
||||
if repeatWeekdays != nil {
|
||||
params["repeatWeekdays"] = repeatWeekdays.String()
|
||||
}
|
||||
if timePoints != nil {
|
||||
params["timePoints"] = timePoints.String()
|
||||
if input.TimePoints != nil && len(input.TimePoints) != 0 {
|
||||
params["timePoints"] = jsonutils.Marshal(input.GetStringArrayTimePoints()).String()
|
||||
}
|
||||
_, err := self.ecsRequest("ModifyAutoSnapshotPolicyEx", params)
|
||||
if err != nil {
|
||||
@@ -259,6 +253,31 @@ func (self *SRegion) UpdateSnapshotPolicy(
|
||||
return nil
|
||||
}
|
||||
|
||||
//func (self *SRegion) UpdateSnapshotPolicy(
|
||||
// snapshotPolicyId string, retentionDays *int,
|
||||
// repeatWeekdays, timePoints *jsonutils.JSONArray, policyName string,
|
||||
//) error {
|
||||
// params := make(map[string]string)
|
||||
// params["RegionId"] = self.RegionId
|
||||
// if len(policyName) > 0 {
|
||||
// params["autoSnapshotPolicyName"] = policyName
|
||||
// }
|
||||
// if retentionDays != nil {
|
||||
// params["retentionDays"] = strconv.Itoa(*retentionDays)
|
||||
// }
|
||||
// if repeatWeekdays != nil {
|
||||
// params["repeatWeekdays"] = repeatWeekdays.String()
|
||||
// }
|
||||
// if timePoints != nil {
|
||||
// params["timePoints"] = timePoints.String()
|
||||
// }
|
||||
// _, err := self.ecsRequest("ModifyAutoSnapshotPolicyEx", params)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("ModifyAutoSnapshotPolicyEx Fail %s", err)
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
|
||||
func (self *SRegion) ApplySnapshotPolicyToDisks(snapshotPolicyId string, diskId string) error {
|
||||
params := make(map[string]string)
|
||||
params["RegionId"] = self.RegionId
|
||||
|
||||
@@ -16,8 +16,8 @@ package multicloud
|
||||
|
||||
type SDisk struct{}
|
||||
|
||||
func (self *SDisk) GetExtSnapshotPolicyIds() []string {
|
||||
return []string{""}
|
||||
func (self *SDisk) GetExtSnapshotPolicyIds() ([]string, error) {
|
||||
return []string{""}, nil
|
||||
}
|
||||
|
||||
func (self *SDisk) GetIStorageId() string {
|
||||
|
||||
@@ -348,6 +348,10 @@ func (self *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
||||
return isnapshots, nil
|
||||
}
|
||||
|
||||
func (self *SDisk) GetExtSnapshotPolicyIds() ([]string, error) {
|
||||
return self.storage.zone.region.GetSnapshotIdByDiskId(self.GetId())
|
||||
}
|
||||
|
||||
func (self *SDisk) GetTemplateId() string {
|
||||
//return self.ImageId
|
||||
return ""
|
||||
|
||||
@@ -43,7 +43,7 @@ type SSnapshotPolicy struct {
|
||||
AutoSnapshotPolicyState string
|
||||
RetentionDays int
|
||||
Policy []SPolicy
|
||||
Activated bool `json:"is_activated"`
|
||||
Activated bool `json:"IsActivated"`
|
||||
IsPermanent bool
|
||||
}
|
||||
|
||||
@@ -90,6 +90,9 @@ func (self *SSnapshotPolicy) GetProjectId() string {
|
||||
}
|
||||
|
||||
func (self *SSnapshotPolicy) GetRetentionDays() int {
|
||||
if self.IsPermanent {
|
||||
return -1
|
||||
}
|
||||
return self.RetentionDays
|
||||
}
|
||||
|
||||
@@ -148,6 +151,9 @@ func (self *SRegion) GetSnapshotPolicies(policyId string, offset int, limit int)
|
||||
if err := body.Unmarshal(&snapshotPolicies, "AutoSnapshotPolicySet"); err != nil {
|
||||
return nil, 0, errors.Wrap(err, "Unmarshal snapshot policies detail failed")
|
||||
}
|
||||
for i := range snapshotPolicies {
|
||||
snapshotPolicies[i].region = self
|
||||
}
|
||||
return snapshotPolicies, len(snapshotPolicies), nil
|
||||
}
|
||||
|
||||
@@ -187,7 +193,14 @@ func (self *SRegion) CreateSnapshotPolicy(input *cloudprovider.SnapshotPolicyInp
|
||||
return "", fmt.Errorf("Can't create snapshot policy with nil timePoints")
|
||||
}
|
||||
params := make(map[string]string)
|
||||
params["RetentionDays"] = strconv.Itoa(input.RetentionDays)
|
||||
|
||||
// In Qcloud, that IsPermanent is true means that keep snapshot forever,
|
||||
// In OneCloud, that RetentionDays is -1 means that keep snapshot forever.
|
||||
if input.RetentionDays == -1 {
|
||||
params["IsPermanent"] = strconv.FormatBool(true)
|
||||
} else {
|
||||
params["RetentionDays"] = strconv.Itoa(input.RetentionDays)
|
||||
}
|
||||
dayOfWeekPrefix, hourPrefix := "Policy.0.DayOfWeek.", "Policy.0.Hour."
|
||||
for index, day := range input.RepeatWeekdays {
|
||||
if day == 0 {
|
||||
@@ -209,10 +222,7 @@ func (self *SRegion) CreateSnapshotPolicy(input *cloudprovider.SnapshotPolicyInp
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) UpdateSnapshotPolicy(
|
||||
snapshotPolicyId string, retentionDays *int,
|
||||
repeatWeekdays, timePoints *jsonutils.JSONArray, policyName string,
|
||||
) error {
|
||||
func (self *SRegion) UpdateSnapshotPolicy(input *cloudprovider.SnapshotPolicyInput, snapshotPolicyId string) error {
|
||||
// not implement
|
||||
return nil
|
||||
}
|
||||
@@ -238,3 +248,23 @@ func (self *SRegion) CancelSnapshotPolicyToDisks(snapshotPolicyId string, diskId
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetSnapshotIdByDiskId(diskID string) ([]string, error) {
|
||||
params := make(map[string]string)
|
||||
params["DiskId"] = diskID
|
||||
|
||||
rps, err := self.cbsRequest("DescribeDiskAssociatedAutoSnapshotPolicy", params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Get All SnapshotpolicyIDs of Disk %s failed", diskID)
|
||||
}
|
||||
|
||||
snapshotpolicies := make([]SSnapshotPolicy, 0)
|
||||
if err := rps.Unmarshal(&snapshotpolicies, "AutoSnapshotPolicySet"); err != nil {
|
||||
return nil, errors.Wrapf(err, "Unmarshal snapshot policies details failed")
|
||||
}
|
||||
ret := make([]string, len(snapshotpolicies))
|
||||
for i := range snapshotpolicies {
|
||||
ret[i] = snapshotpolicies[i].GetId()
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
@@ -26,6 +26,10 @@ func (r *SRegion) CreateSnapshotPolicy(input *cloudprovider.SnapshotPolicyInput)
|
||||
return "", fmt.Errorf("CreateSnapshotPolicy not implement")
|
||||
}
|
||||
|
||||
func (r *SRegion) UpdateSnapshotPolicy(input *cloudprovider.SnapshotPolicyInput, snapshotPolicyId string) error {
|
||||
return fmt.Errorf("UpdateSnapshotPolicy not implement")
|
||||
}
|
||||
|
||||
func (r *SRegion) GetISnapshotPolicyById(snapshotPolicyId string) (cloudprovider.ICloudSnapshotPolicy, error) {
|
||||
return nil, fmt.Errorf("GetISnapshotPolicyById not implement")
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
package bitmap
|
||||
|
||||
// Uint2IntArray transfer bitmap displayed as n to int array
|
||||
func Uint2IntArray(n uint32) []int {
|
||||
ret := make([]int, 0, 2)
|
||||
var i uint = 0
|
||||
@@ -27,6 +28,7 @@ func Uint2IntArray(n uint32) []int {
|
||||
return ret
|
||||
}
|
||||
|
||||
// IntArray2Uint transfer int array nums to bitmap number
|
||||
func IntArray2Uint(nums []int) uint32 {
|
||||
var ret uint32 = 0
|
||||
for _, i := range nums {
|
||||
@@ -34,3 +36,16 @@ func IntArray2Uint(nums []int) uint32 {
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// Determine if int slice a euqals b
|
||||
func IntSliceEqual(a, b []int) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(a); i++ {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -35,24 +35,12 @@ func TestUint2IntArray(t *testing.T) {
|
||||
|
||||
for _, tc := range testCase {
|
||||
real := Uint2IntArray(tc.input)
|
||||
if !sliceEqual(real, tc.want) {
|
||||
if !IntSliceEqual(real, tc.want) {
|
||||
t.Fatalf("want %v, but %v\n", tc.want, real)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sliceEqual(a, b []int) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(a); i++ {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func TestIntArray2Uint(t *testing.T) {
|
||||
oneCase := make([]int, 32)
|
||||
for i := range oneCase {
|
||||
|
||||
39
pkg/util/validate/days.go
Normal file
39
pkg/util/validate/days.go
Normal file
@@ -0,0 +1,39 @@
|
||||
// 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 validate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// DaysValidate sort days and check if days is out of range [min, max] or has repeated member
|
||||
func DaysCheck(days []int, min, max int) ([]int, error) {
|
||||
if len(days) == 0 {
|
||||
return days, nil
|
||||
}
|
||||
sort.Ints(days)
|
||||
|
||||
if days[0] < min || days[len(days)-1] > max {
|
||||
return days, fmt.Errorf("Out of range")
|
||||
}
|
||||
|
||||
for i := 1; i < len(days); i++ {
|
||||
if days[i] == days[i-1] {
|
||||
return days, fmt.Errorf("Has repeat day %v", days)
|
||||
}
|
||||
}
|
||||
return days, nil
|
||||
}
|
||||
63
pkg/util/validate/days_test.go
Normal file
63
pkg/util/validate/days_test.go
Normal file
@@ -0,0 +1,63 @@
|
||||
// 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 validate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDaysCheck(t *testing.T) {
|
||||
tcs := []struct {
|
||||
input_days []int
|
||||
input_max int
|
||||
input_min int
|
||||
want []int
|
||||
want_error error
|
||||
}{
|
||||
{
|
||||
[]int{3, 5, 1, 4, 8, 3, 4},
|
||||
10,
|
||||
1,
|
||||
[]int{1, 3, 3, 4, 4, 5, 8},
|
||||
fmt.Errorf("Has repeat day %v", []int{1, 3, 3, 4, 4, 5, 8}),
|
||||
},
|
||||
{
|
||||
[]int{10, 1},
|
||||
10,
|
||||
1,
|
||||
[]int{1, 10},
|
||||
nil,
|
||||
},
|
||||
{
|
||||
[]int{10, 3, 5},
|
||||
3,
|
||||
5,
|
||||
[]int{3, 5, 10},
|
||||
fmt.Errorf("Out of range"),
|
||||
},
|
||||
}
|
||||
for _, tc := range tcs {
|
||||
days, err := DaysCheck(tc.input_days, tc.input_min, tc.input_max)
|
||||
if !reflect.DeepEqual(days, tc.want) {
|
||||
t.Fatalf("want: %v, actual: %v", tc.want, days)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(err, tc.want_error) {
|
||||
t.Fatal("err not correct")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user