diff --git a/cmd/climc/shell/image/images.go b/cmd/climc/shell/image/images.go index 4fc7cb6b7f..9a7005364e 100644 --- a/cmd/climc/shell/image/images.go +++ b/cmd/climc/shell/image/images.go @@ -143,6 +143,7 @@ func init() { Protected string `help:"filter images by protected" choices:"true|false"` IsUefi bool `help:"list uefi image"` Format []string `help:"Disk formats"` + SubFormats []string `help:"Sub formats"` Name string `help:"Name filter"` } R(&ImageListOptions{}, "image-list", "List images", func(s *mcclient.ClientSession, args *ImageListOptions) error { @@ -173,15 +174,14 @@ func init() { params.Add(jsonutils.NewString(args.Name), "name") } if len(args.Format) > 0 { - if len(args.Format) == 1 { - params.Add(jsonutils.NewString(args.Format[0]), "disk_format") - } else { - fs := jsonutils.NewArray() - for _, f := range args.Format { - fs.Add(jsonutils.NewString(f)) - } - params.Add(fs, "disk_formats") + fs := jsonutils.NewArray() + for _, f := range args.Format { + fs.Add(jsonutils.NewString(f)) } + params.Add(fs, "disk_formats") + } + if len(args.SubFormats) > 0 { + params.Add(jsonutils.Marshal(args.SubFormats), "sub_formats") } result, err := modules.Images.List(s, params) if err != nil { diff --git a/pkg/apis/image/image.go b/pkg/apis/image/image.go index c44ae5650d..f0e88fbc08 100644 --- a/pkg/apis/image/image.go +++ b/pkg/apis/image/image.go @@ -28,6 +28,9 @@ type ImageListInput struct { // 列出是否支持UEFI启动的镜像 Uefi *bool `json:"uefi"` + // 根据已转换格式过滤, 可能值为: qcow2, vmdk, vhd, raw等 + SubFormats []string `json:"subFormats"` + // 是否为标准镜像 IsStandard *bool `json:"is_standard"` diff --git a/pkg/compute/guestdrivers/azure.go b/pkg/compute/guestdrivers/azure.go index 2e7e7b45e5..e42f345c52 100644 --- a/pkg/compute/guestdrivers/azure.go +++ b/pkg/compute/guestdrivers/azure.go @@ -19,14 +19,18 @@ import ( "fmt" "yunion.io/x/jsonutils" + "yunion.io/x/pkg/errors" "yunion.io/x/pkg/utils" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas" "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/mcclient/auth" + "yunion.io/x/onecloud/pkg/mcclient/modules" "yunion.io/x/onecloud/pkg/util/billing" "yunion.io/x/onecloud/pkg/util/rbacutils" ) @@ -123,6 +127,37 @@ func (self *SAzureGuestDriver) ValidateCreateData(ctx context.Context, userCred if len(input.Networks) > 2 { return nil, httperrors.NewInputParameterError("cannot support more than 1 nic") } + if len(input.Disks) > 0 && len(input.Disks[0].ImageId) > 0 { + _image, err := models.CachedimageManager.FetchById(input.Disks[0].ImageId) + if err != nil { + return nil, errors.Wrap(err, "FetchById") + } + image := _image.(*models.SCachedimage) + if len(image.ExternalId) == 0 { + s := auth.GetAdminSession(ctx, options.Options.Region, "") + result, err := modules.Images.GetSpecific(s, image.Id, "subformats", nil) + if err != nil { + return nil, errors.Wrap(err, "get subformats") + } + subFormats := []struct { + Format string + }{} + err = result.Unmarshal(&subFormats) + if err != nil { + return nil, errors.Wrap(err, "Unmarshal subformats") + } + find := false + for i := range subFormats { + if subFormats[i].Format == "vhd" { + find = true + break + } + } + if !find { + return nil, httperrors.NewResourceNotFoundError("failed to find subformat vhd for image %s, please append 'vhd' for glance options(target_image_formats)", image.Name) + } + } + } return input, nil } diff --git a/pkg/image/models/images.go b/pkg/image/models/images.go index 4cbf492a4d..c9e17f47e9 100644 --- a/pkg/image/models/images.go +++ b/pkg/image/models/images.go @@ -1156,6 +1156,10 @@ func (manager *SImageManager) ListItemFilter( if len(query.DiskFormats) > 0 { q = q.In("disk_format", query.DiskFormats) } + if len(query.SubFormats) > 0 { + sq := ImageSubformatManager.Query().SubQuery() + q = q.Join(sq, sqlchemy.Equals(sq.Field("image_id"), q.Field("id"))).Filter(sqlchemy.In(sq.Field("format"), query.SubFormats)) + } if query.Uefi != nil && *query.Uefi { imagePropertyQ := ImagePropertyManager.Query(). Equals("name", api.IMAGE_UEFI_SUPPORT).Equals("value", "true").SubQuery()