func (a CreateStemcellMethod) CreateStemcell(imagePath string, cloudProps apiv1.StemcellCloudProps) (apiv1.StemcellCID, error) {
	var props StemcellProps
	var stemcellId string
	err := cloudProps.As(&props)
	if err != nil {
		return apiv1.StemcellCID{}, bosherr.WrapErrorf(err, "BadInput for CreateStemcell %s", cloudProps)
	}
	props, err = props.Validate()
	if err != nil {
		return apiv1.StemcellCID{}, bosherr.WrapErrorf(err, "BadInput for CreateStemcell %3v", err)
	}
	switch {
	case len(props.Images) > 0:
		stemcellId, err = props.FindStemcellId(a.Config.OpenApi.GetRegion(""))
	case props.OSSBucket != "" && props.OSSObject != "":
		stemcellId, err = a.CreateFromURL(props)
	default:
		stemcellId, err = a.CreateFromTarball(imagePath, props)
	}
	if err != nil {
		return apiv1.StemcellCID{}, bosherr.WrapErrorf(err, "Importing stemcell from '%s'", imagePath)
	}
	stemcellId, err = a.copyImage(stemcellId, props)
	if err != nil {
		return apiv1.StemcellCID{}, bosherr.WrapErrorf(err, "Copying stemcell from '%s'", imagePath)
	}
	return apiv1.NewStemcellCID(stemcellId), nil
}
create stemcell policy:
1. stemcell metadate set in cloudProps
2. we provide three ways to create stemcell
2.1 region-imageId format, return Stemcell directly
2.2 source URL, put the raw image on OSS, then create image by the oss url
2.3 local tarball, upload the tarball on OSS, the create image by the oss url
package action
import (
	"bosh-alicloud-cpi/alicloud"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
	"bytes"
	"os/exec"
	"path"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
	"github.com/aliyun/aliyun-oss-go-sdk/oss"
	bosherr "github.com/cloudfoundry/bosh-utils/errors"
	"github.com/cppforlife/bosh-cpi-go/apiv1"
	"github.com/google/uuid"
)
const (
	AlicloudImageNamePrefix    = "stemcell"
	MinImageDiskSize           = 5  
	OSS_BUCKET_NAME_MAX_LENGTH = 64
	PART_SIZE                  = 5 * 1024 * 1024  
)
type StemcellProps struct {
	Architecture    string      `json:"architecture"`
	ContainerFormat string      `json:"container_format"`
	Disk            interface{} `json:"disk"`
	DiskFormat      string      `json:"disk_format"`
	diskGB          int
	Hypervisor      string `json:"hypervisor"`
	Name            string `json:"name"`
	OsDistro        string `json:"os_distro"`
	OsType          string `json:"os_type"`
	SourceUrl string `json:"source_url"`
	OSSBucket   string                 `json:"oss_bucket"`
	OSSObject   string                 `json:"oss_object"`
	Description string                 `json:"description,omitempty"`
	Version     string                 `json:"version"`
	Images      map[string]interface{} `json:"image_id"`
}
type CreateStemcellMethod struct {
	CallContext
	stemcells alicloud.StemcellManager
	instances alicloud.InstanceManager
	osses     alicloud.OssManager
}
func NewCreateStemcellMethod(cc CallContext, stemcells alicloud.StemcellManager, instances alicloud.InstanceManager, osses alicloud.OssManager) CreateStemcellMethod {
	return CreateStemcellMethod{cc, stemcells, instances, osses}
}
func (a StemcellProps) Validate() (StemcellProps, error) {
	if a.Disk != nil {
		switch a.Disk.(type) {
		case int:
			a.diskGB = ConvertToGB(float64(a.Disk.(int)))
			if a.diskGB < 1 {
				return a, fmt.Errorf("disk size too small %dMB < 1GB", a.Disk.(int))
			}
		case float64:
			a.diskGB = ConvertToGB(a.Disk.(float64))
			if a.diskGB < 1 {
				return a, fmt.Errorf("disk size too small %fMB < 1GB", a.Disk.(float64))
			}
		case string:
			s, _ := a.Disk.(string)
			if strings.Compare("", s) == 0 {
				a.diskGB = 0
			}
			s = strings.Replace(s, "_", "", -1)
			n, err := strconv.Atoi(s)
			if err != nil {
				return a, fmt.Errorf("error Disk.size format %v", a.Disk)
			}
			a.diskGB = ConvertToGB(float64(n))
			if a.diskGB < 1 {
				return a, fmt.Errorf("disk size too small %dMB < 1GB", n)
			}
		default:
			return a, fmt.Errorf("error Disk.size type %v", a.Disk)
		}
	} else {
		a.diskGB = 0
	}
	return a, nil
}
func (a StemcellProps) GetDiskGB() int {
	if a.diskGB < MinImageDiskSize {
		return MinImageDiskSize
	}
	return a.diskGB
}