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:
yunion-ci-robot
2019-07-22 10:04:05 +08:00
committed by GitHub
12 changed files with 103 additions and 36 deletions
+1 -1
View File
@@ -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
View File
@@ -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
})
+16
View File
@@ -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
+2
View File
@@ -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
View File
@@ -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: 操作系统版本
+3
View File
@@ -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)
+11 -8
View File
@@ -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
+4
View File
@@ -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 {
+5
View File
@@ -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
+9
View File
@@ -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
View File
@@ -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
}
+2 -2
View File
@@ -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",