mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-29 03:51:54 +08:00
Merge pull request #1815 from swordqiu/hotfix/qj-imaage-standard-field
fix: image add is_standard field, filter by is_standard=false|true
This commit is contained in:
@@ -78,7 +78,7 @@ func init() {
|
||||
|
||||
type DiskDeleteOptions struct {
|
||||
ID []string `help:"ID of disks to delete" metavar:"DISK"`
|
||||
OverridePendingDelete bool `help:"Delete disk directly instead of pending delete"`
|
||||
OverridePendingDelete bool `help:"Delete disk directly instead of pending delete" short-token:"f"`
|
||||
}
|
||||
|
||||
R(&DiskDeleteOptions{}, "disk-delete", "Delete a disk", func(s *mcclient.ClientSession, args *DiskDeleteOptions) error {
|
||||
|
||||
+23
-10
@@ -33,6 +33,8 @@ type ImageOptionalOptions struct {
|
||||
Format string `help:"Image format" choices:"raw|qcow2|iso|vmdk|docker|vhd"`
|
||||
Protected bool `help:"Prevent image from being deleted"`
|
||||
Unprotected bool `help:"Allow image to be deleted"`
|
||||
Standard bool `help:"Mark image as a standard image"`
|
||||
Nonstandard bool `help:"Mark image as a non-standard image"`
|
||||
MinDisk int64 `help:"Disk size after expanded, in MB" metavar:"MIN_DISK_SIZE_MB"`
|
||||
MinRam int64 `help:"Minimal memory size required" metavar:"MIN_RAM_MB"`
|
||||
VirtualSize int64 `help:"Disk size after expanded, in MB"`
|
||||
@@ -69,6 +71,11 @@ func addImageOptionalOptions(s *mcclient.ClientSession, params *jsonutils.JSONDi
|
||||
} else if !args.Protected && args.Unprotected {
|
||||
params.Add(jsonutils.NewString("false"), "protected")
|
||||
}
|
||||
if args.Standard && !args.Nonstandard {
|
||||
params.Add(jsonutils.JSONTrue, "is_standard")
|
||||
} else if !args.Standard && args.Nonstandard {
|
||||
params.Add(jsonutils.JSONFalse, "is_standard")
|
||||
}
|
||||
if args.MinDisk > 0 {
|
||||
params.Add(jsonutils.NewString(fmt.Sprintf("%d", args.MinDisk)), "min_disk")
|
||||
}
|
||||
@@ -134,9 +141,11 @@ func init() {
|
||||
type ImageListOptions struct {
|
||||
options.BaseListOptions
|
||||
|
||||
IsPublic string `help:"filter images public or not(True, False or None)" choices:"true|false|none"`
|
||||
Format []string `help:"Disk formats"`
|
||||
Name string `help:"Name filter"`
|
||||
IsPublic string `help:"filter images public or not(True, False or None)" choices:"true|false"`
|
||||
IsStandard string `help:"filter images standard or non-standard" choices:"true|false"`
|
||||
Protected string `help:"filter images by protected" choices:"true|false"`
|
||||
Format []string `help:"Disk formats"`
|
||||
Name string `help:"Name filter"`
|
||||
}
|
||||
R(&ImageListOptions{}, "image-list", "List images", func(s *mcclient.ClientSession, args *ImageListOptions) error {
|
||||
params, err := args.Params()
|
||||
@@ -146,6 +155,12 @@ func init() {
|
||||
if len(args.IsPublic) > 0 {
|
||||
params.Add(jsonutils.NewString(args.IsPublic), "is_public")
|
||||
}
|
||||
if len(args.IsStandard) > 0 {
|
||||
params.Add(jsonutils.NewString(args.IsStandard), "is_standard")
|
||||
}
|
||||
if len(args.Protected) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Protected), "protected")
|
||||
}
|
||||
if len(args.Tenant) > 0 {
|
||||
tid, e := modules.Projects.GetId(s, args.Tenant, nil)
|
||||
if e != nil {
|
||||
@@ -268,7 +283,7 @@ func init() {
|
||||
|
||||
type ImageDeleteOptions struct {
|
||||
ID []string `help:"Image ID or name"`
|
||||
OverridePendingDelete *bool `help:"Delete image directly instead of pending delete"`
|
||||
OverridePendingDelete *bool `help:"Delete image directly instead of pending delete" short-token:"f"`
|
||||
}
|
||||
R(&ImageDeleteOptions{}, "image-delete", "Delete a image", func(s *mcclient.ClientSession, args *ImageDeleteOptions) error {
|
||||
params, err := options.StructToParams(args)
|
||||
@@ -447,18 +462,16 @@ func init() {
|
||||
|
||||
R(&ImageOperationOptions{}, "image-mark-standard", "Mark image standard", func(s *mcclient.ClientSession, args *ImageOperationOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.JSONTrue, "is-public")
|
||||
params.Add(jsonutils.JSONTrue, "protected")
|
||||
results := modules.Images.BatchPerformAction(s, args.ID, "mark-public-protected", params)
|
||||
params.Add(jsonutils.JSONTrue, "is_standard")
|
||||
results := modules.Images.BatchPerformAction(s, args.ID, "mark-standard", params)
|
||||
printBatchResults(results, modules.Images.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
R(&ImageOperationOptions{}, "image-mark-unstandard", "Mark image not standard", func(s *mcclient.ClientSession, args *ImageOperationOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.JSONFalse, "is-public")
|
||||
params.Add(jsonutils.JSONFalse, "protected")
|
||||
results := modules.Images.BatchPerformAction(s, args.ID, "mark-public-protected", params)
|
||||
params.Add(jsonutils.JSONFalse, "is_standard")
|
||||
results := modules.Images.BatchPerformAction(s, args.ID, "mark-standard", params)
|
||||
printBatchResults(results, modules.Images.GetColumns(s))
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
post:
|
||||
parameters:
|
||||
- $ref: "../parameters/image.yaml#/imageId"
|
||||
- in: body
|
||||
name: image
|
||||
required: true
|
||||
schema:
|
||||
$ref: "../schemas/image.yaml#/ImageMarkStandard"
|
||||
summary: 设置/取消设置镜像为标准镜像
|
||||
responses:
|
||||
200:
|
||||
description: 镜像信息
|
||||
schema:
|
||||
$ref: "../schemas/image.yaml#/ImageResponse"
|
||||
tags:
|
||||
- images
|
||||
@@ -168,6 +168,8 @@ paths:
|
||||
$ref: "./image/images.yaml"
|
||||
/images/{imageId}:
|
||||
$ref: "./image/image.yaml"
|
||||
/images/{imageId}/mark-standard:
|
||||
$ref: "./image/image-standard.yaml"
|
||||
|
||||
/natgateways:
|
||||
$ref: "./natgateway/natgateways.yaml"
|
||||
|
||||
+10
-1
@@ -11,6 +11,7 @@ ImageListResponse:
|
||||
total:
|
||||
type: integer
|
||||
example: 124
|
||||
|
||||
ImageResponse:
|
||||
type: object
|
||||
properties:
|
||||
@@ -18,6 +19,14 @@ ImageResponse:
|
||||
type: object
|
||||
$ref: '#/Image'
|
||||
|
||||
ImageMarkStandard:
|
||||
type: object
|
||||
properties:
|
||||
is_standard:
|
||||
type: bool
|
||||
example: true
|
||||
description: 设置镜像是否为标准镜像
|
||||
|
||||
Image:
|
||||
type: object
|
||||
description: 镜像
|
||||
@@ -112,4 +121,4 @@ ImageProperties:
|
||||
os_version:
|
||||
type: string
|
||||
example: 16.0
|
||||
description: 操作系统版本
|
||||
description: 操作系统版本
|
||||
|
||||
@@ -166,6 +166,9 @@ func (manager *SHostManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
|
||||
q = managedResourceFilterByCloudType(q, query, "", nil)
|
||||
|
||||
q, err = managedResourceFilterByDomain(q, query, "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
queryDict := query.(*jsonutils.JSONDict)
|
||||
|
||||
|
||||
@@ -391,18 +391,21 @@ func (self *SStoragecache) GetIStorageCache() (cloudprovider.ICloudStoragecache,
|
||||
}
|
||||
|
||||
func (manager *SStoragecacheManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
|
||||
q, err := manager.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
var err error
|
||||
q, err = managedResourceFilterByAccount(q, query, "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q = managedResourceFilterByCloudType(q, query, "", nil)
|
||||
|
||||
q, err = managedResourceFilterByDomain(q, query, "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
managerStr := jsonutils.GetAnyString(query, []string{"manager", "provider", "manager_id", "provider_id"})
|
||||
if len(managerStr) > 0 {
|
||||
provider := CloudproviderManager.FetchCloudproviderByIdOrName(managerStr)
|
||||
if provider == nil {
|
||||
return nil, httperrors.NewResourceNotFoundError("provider %s not found", managerStr)
|
||||
}
|
||||
q = q.Filter(sqlchemy.Equals(q.Field("manager_id"), provider.GetId()))
|
||||
q, err = manager.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return q, nil
|
||||
|
||||
@@ -1052,6 +1052,10 @@ func (manager *SStorageManager) ListItemFilter(ctx context.Context, q *sqlchemy.
|
||||
return nil, err
|
||||
}
|
||||
q = managedResourceFilterByCloudType(q, query, "", nil)
|
||||
q, err = managedResourceFilterByDomain(q, query, "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
q, err = manager.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
|
||||
@@ -651,6 +651,11 @@ func (manager *SVpcManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQue
|
||||
}
|
||||
q = managedResourceFilterByCloudType(q, query, "", nil)
|
||||
|
||||
q, err = managedResourceFilterByDomain(q, query, "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
q, err = manager.SStatusStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -733,6 +733,15 @@ func (manager *SWireManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
|
||||
return subq
|
||||
})
|
||||
|
||||
q, err = managedResourceFilterByDomain(q, query, "vpc_id", func() *sqlchemy.SQuery {
|
||||
vpcs := VpcManager.Query().SubQuery()
|
||||
subq := vpcs.Query(vpcs.Field("id"))
|
||||
return subq
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
q, err = manager.SStandaloneResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
+17
-14
@@ -114,7 +114,8 @@ type SImage struct {
|
||||
MinDiskMB int32 `name:"min_disk" nullable:"false" default:"0" list:"user" create:"optional" update:"user"`
|
||||
MinRamMB int32 `name:"min_ram" nullable:"false" default:"0" list:"user" create:"optional" update:"user"`
|
||||
|
||||
Protected tristate.TriState `nullable:"true" list:"user" get:"user" create:"optional" update:"user"`
|
||||
Protected tristate.TriState `nullable:"false" default:"true" list:"user" get:"user" create:"optional" update:"user"`
|
||||
IsStandard tristate.TriState `nullable:"false" default:"false" list:"user" get:"user" create:"admin_optional"`
|
||||
|
||||
// image copy from url, save origin checksum before probe
|
||||
OssChecksum string `width:"32" charset:"ascii" nullable:"true" get:"user" list:"user"`
|
||||
@@ -569,12 +570,15 @@ func (self *SImage) AllowDeleteItem(ctx context.Context, userCred mcclient.Token
|
||||
}
|
||||
|
||||
func (self *SImage) ValidateDeleteCondition(ctx context.Context) error {
|
||||
if self.IsPublic {
|
||||
return httperrors.NewInvalidStatusError("image is shared")
|
||||
if self.IsStandard.IsTrue() {
|
||||
return httperrors.NewForbiddenError("image is standard image")
|
||||
}
|
||||
if self.Protected.IsTrue() {
|
||||
return httperrors.NewForbiddenError("image is protected")
|
||||
}
|
||||
if self.IsPublic {
|
||||
return httperrors.NewInvalidStatusError("image is shared")
|
||||
}
|
||||
return self.SVirtualResourceBase.ValidateDeleteCondition(ctx)
|
||||
}
|
||||
|
||||
@@ -1123,36 +1127,35 @@ func (self *SImage) DoCheckStatus(ctx context.Context, userCred mcclient.TokenCr
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SImage) AllowPerformMarkPublicProtected(
|
||||
func (self *SImage) AllowPerformMarkStandard(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
data jsonutils.JSONObject,
|
||||
) bool {
|
||||
return db.IsAdminAllowPerform(userCred, self, "mark-public-protected")
|
||||
return db.IsAdminAllowPerform(userCred, self, "mark-standard")
|
||||
}
|
||||
|
||||
func (self *SImage) PerformMarkPublicProtected(
|
||||
func (self *SImage) PerformMarkStandard(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
data jsonutils.JSONObject,
|
||||
) (jsonutils.JSONObject, error) {
|
||||
isPublic := jsonutils.QueryBoolean(data, "is-public", false)
|
||||
protected := jsonutils.QueryBoolean(data, "protected", false)
|
||||
if isPublic != self.IsPublic || (!self.Protected.IsTrue() && protected) || (self.Protected.IsTrue() && !protected) {
|
||||
_, err := db.Update(self, func() error {
|
||||
self.IsPublic = isPublic
|
||||
if protected {
|
||||
self.Protected = tristate.True
|
||||
isStandard := jsonutils.QueryBoolean(data, "is_standard", false)
|
||||
if (!self.IsStandard.IsTrue() && isStandard) || (self.IsStandard.IsTrue() && !isStandard) {
|
||||
diff, err := db.Update(self, func() error {
|
||||
if isStandard {
|
||||
self.IsStandard = tristate.True
|
||||
} else {
|
||||
self.Protected = tristate.False
|
||||
self.IsStandard = tristate.False
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, httperrors.NewGeneralError(err)
|
||||
}
|
||||
db.OpsLog.LogEvent(self, db.ACT_UPDATE, diff, userCred)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -567,8 +567,8 @@ var (
|
||||
func init() {
|
||||
Images = ImageManager{NewImageManager("image", "images",
|
||||
[]string{"ID", "Name", "Tags", "Disk_format",
|
||||
"Size", "Is_public", "OS_Type",
|
||||
"OS_Distribution", "OS_version",
|
||||
"Size", "Is_public", "Protected", "Is_Standard",
|
||||
"OS_Type", "OS_Distribution", "OS_version",
|
||||
"Min_disk", "Min_ram", "Status",
|
||||
"Notes", "OS_arch", "Preference",
|
||||
"OS_Codename", "Description",
|
||||
|
||||
Reference in New Issue
Block a user