// 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 compute import ( "net/http" "reflect" "time" "yunion.io/x/cloudmux/pkg/apis/compute" "yunion.io/x/cloudmux/pkg/cloudprovider" "yunion.io/x/pkg/errors" "yunion.io/x/pkg/gotypes" "yunion.io/x/pkg/util/regutils" "yunion.io/x/pkg/utils" "yunion.io/x/onecloud/pkg/apis" "yunion.io/x/onecloud/pkg/httperrors" ) const ( BUCKET_OPS_STATS_CHANGE = "stats_change" BUCKET_STATUS_START_CREATE = "start_create" BUCKET_STATUS_CREATING = "creating" BUCKET_STATUS_READY = compute.BUCKET_STATUS_READY BUCKET_STATUS_CREATE_FAIL = "create_fail" BUCKET_STATUS_START_DELETE = "start_delete" BUCKET_STATUS_DELETING = "deleting" BUCKET_STATUS_DELETED = "deleted" BUCKET_STATUS_DELETE_FAIL = "delete_fail" BUCKET_STATUS_UNKNOWN = "unknown" BUCKET_UPLOAD_OBJECT_KEY_HEADER = "X-Yunion-Bucket-Upload-Key" BUCKET_UPLOAD_OBJECT_ACL_HEADER = "X-Yunion-Bucket-Upload-Acl" BUCKET_UPLOAD_OBJECT_STORAGECLASS_HEADER = "X-Yunion-Bucket-Upload-Storageclass" ) type BucketCreateInput struct { apis.SharableVirtualResourceCreateInput CloudregionResourceInput CloudproviderResourceInput StorageClass string `json:"storage_class"` EnablePerfMon *bool `json:"enable_perf_mon"` } type BucketDetails struct { apis.SharableVirtualResourceDetails ManagedResourceInfo CloudregionResourceInfo SBucket // 访问URL列表 AccessUrls []cloudprovider.SBucketAccessUrl `json:"access_urls"` } func (bucket BucketDetails) GetMetricTags() map[string]string { ret := map[string]string{ "id": bucket.Id, "brand": bucket.Brand, "cloudregion": bucket.Cloudregion, "cloudregion_id": bucket.CloudregionId, "domain_id": bucket.DomainId, "oss_id": bucket.Id, "oss_name": bucket.Name, "project_domain": bucket.ProjectDomain, "region_ext_id": bucket.RegionExtId, "status": bucket.Status, "tenant": bucket.Project, "tenant_id": bucket.ProjectId, "account": bucket.Account, "account_id": bucket.AccountId, "external_id": bucket.ExternalId, } return AppendMetricTags(ret, bucket.MetadataResourceInfo, bucket.ProjectizedResourceInfo) } func (bucket BucketDetails) GetMetricPairs() map[string]string { ret := map[string]string{} return ret } type BucketObjectsActionInput struct { Key []string `json:"key"` } type BucketAclInput struct { BucketObjectsActionInput Acl cloudprovider.TBucketACLType } func (input *BucketAclInput) Validate() error { switch input.Acl { case cloudprovider.ACLPrivate, cloudprovider.ACLAuthRead, cloudprovider.ACLPublicRead, cloudprovider.ACLPublicReadWrite: // do nothing default: return errors.Wrap(httperrors.ErrInputParameter, "acl") } return nil } type BucketMetadataInput struct { BucketObjectsActionInput Metadata http.Header } func (input *BucketMetadataInput) Validate() error { if len(input.Key) == 0 { return errors.Wrap(httperrors.ErrEmptyRequest, "key") } if len(input.Metadata) == 0 { return errors.Wrap(httperrors.ErrEmptyRequest, "metadata") } return nil } type BucketListInput struct { apis.SharableVirtualResourceListInput apis.ExternalizedResourceBaseListInput ManagedResourceListInput RegionalFilterListInput // STORAGE_CLASS StorageClass []string `json:"storage_class"` // 位置 Location []string `json:"location"` // ACL Acl []string `json:"acl"` } type BucketSyncstatusInput struct { } type BucketUpdateInput struct { apis.SharableVirtualResourceBaseUpdateInput EnablePerfMon *bool `json:"enable_perf_mon"` } type BucketPerformTempUrlInput struct { // 访问对象方法 Method string `json:"method"` // 对象KEY // required:true Key string `json:"key"` // 过期时间,单位秒 ExpireSeconds *int `json:"expire_seconds"` } type BucketPerformTempUrlOutput struct { // 生成的临时URL Url string `json:"url"` } type BucketPerformMakedirInput struct { // 目录对象KEY // required:true Key string `json:"key"` } type BucketPerformDeleteInput struct { // 待删除对象KEY // required:true Keys []string `json:"keys"` } type BucketGetAclInput struct { // 对象KEY // required:false Key string `json:"key"` } type BucketGetAclOutput struct { // ACL Acl string `json:"acl"` } type BucketGetObjectsInput struct { // Prefix Prefix string `json:"prefix"` // 是否模拟列举目录模式 Recursive *bool `json:"recursive"` // 分页标识 PagingMarker string `json:"paging_marker"` // 最大输出条目数 Limit *int `json:"limit"` } type BucketGetObjectsOutput struct { // 对象列表 Data []cloudprovider.SCloudObject `json:"data"` // 排序字段,总是key // example: key MarkerField string `json:"marker_field"` // 排序顺序,总是降序 // example: DESC MarkerOrder string `json:"marker_order"` // 下一页请求的paging_marker标识 NextMarker string `json:"next_marker"` } type BucketWebsiteRoutingRule struct { ConditionErrorCode string `json:"condition_error_code"` ConditionPrefix string `json:"condition_prefix"` RedirectProtocol string `json:"redirect_protocol"` RedirectReplaceKey string `json:"redirect_replace_key"` RedirectReplaceKeyPrefix string `json:"redirect_replace_key_prefix"` } type BucketWebsiteConf struct { // 主页 Index string `json:"index"` // 错误时返回的文档 ErrorDocument string `json:"error_document"` // http或https Protocol string `json:"protocol"` Rules []BucketWebsiteRoutingRule `json:"rules"` // 访问网站url Url string `json:"url"` } func (input *BucketWebsiteConf) Validate() error { if len(input.Index) == 0 { return httperrors.NewMissingParameterError("index") } if len(input.ErrorDocument) == 0 { return httperrors.NewMissingParameterError("error_document") } if len(input.Protocol) == 0 { return httperrors.NewMissingParameterError("protocol") } return nil } type BucketCORSRule struct { AllowedMethods []string `json:"allowed_methods"` // 允许的源站,可以是* AllowedOrigins []string `json:"allowed_origins"` AllowedHeaders []string `json:"allowed_headers"` MaxAgeSeconds int `json:"max_age_seconds"` ExposeHeaders []string `json:"expose_headers"` // 规则区别标识 Id string `json:"id"` } type BucketCORSRules struct { Data []BucketCORSRule `json:"data"` } type BucketCORSRuleDeleteInput struct { Id []string `json:"id"` } type BucketPolicy struct { Data []BucketPolicyStatement `json:"data"` } type BucketPolicyStatement struct { // 授权的目标主体 Principal map[string][]string `json:"Principal,omitempty"` // 授权的行为 Action []string `json:"Action,omitempty"` // Allow|Deny Effect string `json:"Effect,omitempty"` // 被授权的资源地址 Resource []string `json:"Resource,omitempty"` // 触发授权的条件 Condition map[string]map[string]interface{} `json:"Condition,omitempty"` // 解析字段,主账号id:子账号id PrincipalId []string `json:"principal_id"` // map[主账号id:子账号id]子账号name PrincipalNames map[string]string `json:"principal_names"` // Read|ReadWrite|FullControl CannedAction string `json:"canned_action"` // 资源路径 ResourcePath []string `json:"resource_path"` // 根据index 生成 Id string `json:"id"` } type BucketPolicyStatementInput struct { // 主账号id:子账号id PrincipalId []string `json:"principal_id"` // Read|ReadWrite|FullControl CannedAction string `json:"canned_action"` // Allow|Deny Effect string `json:"effect"` // 被授权的资源地址,/* ResourcePath []string `json:"resource_path"` // ip 条件 IpEquals []string `json:"ip_equals"` IpNotEquals []string `json:"ip_not_equals"` } func (input *BucketPolicyStatementInput) Validate() error { cannedAction := []string{"Read", "ReadWrite", "FullControl"} if !utils.IsInStringArray(input.CannedAction, cannedAction) { return httperrors.NewInputParameterError("invalid CannedAction %s ", input.CannedAction) } if input.Effect != "Allow" && input.Effect != "Deny" { return httperrors.NewInputParameterError("invalid Effect %s ", input.Effect) } for i := range input.IpEquals { if !regutils.MatchIP4Addr(input.IpEquals[i]) && !regutils.MatchCIDR(input.IpEquals[i]) { return httperrors.NewInputParameterError("invalid ipv4 %s ", input.IpEquals[i]) } } for i := range input.IpNotEquals { if !regutils.MatchIP4Addr(input.IpNotEquals[i]) && !regutils.MatchCIDR(input.IpNotEquals[i]) { return httperrors.NewInputParameterError("invalid ipv4 %s ", input.IpNotEquals[i]) } } return nil } type BucketPolicyDeleteInput struct { Id []string `json:"id"` } func (input *BucketCORSRules) Validate() error { for i := range input.Data { if len(input.Data[i].AllowedOrigins) == 0 { return httperrors.NewMissingParameterError("allowed_origins") } if len(input.Data[i].AllowedMethods) == 0 { return httperrors.NewMissingParameterError("allowed_methods") } } return nil } type BucketRefererConf struct { // Referer Type // enmu: Black-List, White-List RefererType string `json:"referer_type"` // 域名列表 DomainList []string `json:"domain_list"` // 是否允许空referer 访问 AllowEmptyRefer bool `json:"allow_empty_refer"` // 是否开启 Enabled bool `json:"enabled"` } func (input *BucketRefererConf) Validate() error { return nil } func init() { gotypes.RegisterSerializable(reflect.TypeOf(&SBackupStorageAccessInfo{}), func() gotypes.ISerializable { return &SBackupStorageAccessInfo{} }) } type BucketProbeResult struct { UploadTime time.Duration `json:"upload_time"` DownloadTime time.Duration `json:"download_time"` DeleteTime time.Duration `json:"delete_time"` } func (result BucketProbeResult) UploadDelayMs() float64 { return float64(result.UploadTime) / float64(time.Millisecond) } func (result BucketProbeResult) DownloadDelayMs() float64 { return float64(result.DownloadTime) / float64(time.Millisecond) } func (result BucketProbeResult) DeleteDelayMs() float64 { return float64(result.DeleteTime) / float64(time.Millisecond) } func (result BucketProbeResult) UploadThroughputMbps(sizeMBytes int) float64 { return float64(sizeMBytes) * 8 / float64(result.UploadTime.Seconds()) } func (result BucketProbeResult) DownloadThroughputMbps(sizeMBytes int) float64 { return float64(sizeMBytes) * 8 / float64(result.DownloadTime.Seconds()) }