yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/openstack/flavor.go (about) 1 // Copyright 2019 Yunion 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package openstack 16 17 import ( 18 "fmt" 19 "net/url" 20 21 "github.com/pkg/errors" 22 23 "yunion.io/x/jsonutils" 24 25 api "yunion.io/x/cloudmux/pkg/apis/compute" 26 "yunion.io/x/cloudmux/pkg/cloudprovider" 27 "yunion.io/x/cloudmux/pkg/multicloud" 28 ) 29 30 type SFlavor struct { 31 multicloud.SServerSku 32 OpenStackTags 33 region *SRegion 34 35 Id string 36 Disk int 37 Ephemeral int 38 ExtraSpecs ExtraSpecs 39 OriginalName string 40 Name string 41 RAM int 42 Swap string 43 Vcpus int 44 } 45 46 func (region *SRegion) GetFlavors() ([]SFlavor, error) { 47 resource := "/flavors/detail" 48 flavors := []SFlavor{} 49 query := url.Values{} 50 for { 51 resp, err := region.ecsList(resource, query) 52 if err != nil { 53 return nil, errors.Wrap(err, "ecsList") 54 } 55 part := struct { 56 Flavors []SFlavor 57 FlavorsLinks SNextLinks 58 }{} 59 err = resp.Unmarshal(&part) 60 if err != nil { 61 return nil, errors.Wrap(err, "resp.Unmarshal") 62 } 63 flavors = append(flavors, part.Flavors...) 64 65 marker := part.FlavorsLinks.GetNextMark() 66 if len(marker) == 0 { 67 break 68 } 69 query.Set("marker", marker) 70 } 71 return flavors, nil 72 } 73 74 func (region *SRegion) GetFlavor(flavorId string) (*SFlavor, error) { 75 resource := fmt.Sprintf("/flavors/%s", flavorId) 76 resp, err := region.ecsGet(resource) 77 if err != nil { 78 return nil, errors.Wrap(err, "ecsGet") 79 } 80 flavor := &SFlavor{region: region} 81 err = resp.Unmarshal(flavor, "flavor") 82 if err != nil { 83 return nil, errors.Wrap(err, "resp.Unmarshal") 84 } 85 return flavor, nil 86 } 87 88 func (region *SRegion) SyncFlavor(name string, cpu, memoryMb, diskGB int) (string, error) { 89 flavor, err := region.syncFlavor(name, cpu, memoryMb, diskGB) 90 if err != nil { 91 return "", errors.Wrapf(err, "syncFlavor") 92 } 93 return flavor.Id, nil 94 } 95 96 func (region *SRegion) syncFlavor(name string, cpu, memoryMb, diskGB int) (*SFlavor, error) { 97 flavors, err := region.GetFlavors() 98 if err != nil { 99 return nil, errors.Wrapf(err, "GetFlavors") 100 } 101 102 if cpu == 0 && memoryMb == 0 { 103 return nil, fmt.Errorf("failed to find instance type %s", name) 104 } 105 106 for i := range flavors { 107 flavor := flavors[i] 108 flavorName := flavor.GetName() 109 if (len(name) == 0 || flavorName == name || flavorName == fmt.Sprintf("%s-%d", name, diskGB)) && 110 flavor.GetCpuCoreCount() == cpu && 111 flavor.GetMemorySizeMB() == memoryMb && 112 diskGB <= flavor.GetSysDiskMaxSizeGB() { 113 return &flavor, nil 114 } 115 } 116 if len(name) == 0 { 117 name = fmt.Sprintf("ecs.g1.c%dm%d", cpu, memoryMb/1024) 118 } 119 name = fmt.Sprintf("%s-%d", name, diskGB) 120 flavor, err := region.CreateFlavor(name, cpu, memoryMb, diskGB) 121 if err != nil { 122 return nil, errors.Wrap(err, "CreateFlavor") 123 } 124 return flavor, nil 125 } 126 127 func (region *SRegion) CreateISku(opts *cloudprovider.SServerSkuCreateOption) (cloudprovider.ICloudSku, error) { 128 flavor, err := region.CreateFlavor(opts.Name, opts.CpuCount, opts.VmemSizeMb, opts.SysDiskMaxSizeGb) 129 if err != nil { 130 return nil, errors.Wrapf(err, "CreateFlavor") 131 } 132 return flavor, nil 133 } 134 135 func (region *SRegion) CreateFlavor(name string, cpu int, memoryMb int, diskGB int) (*SFlavor, error) { 136 if diskGB <= 0 { 137 diskGB = 30 138 } 139 params := map[string]map[string]interface{}{ 140 "flavor": { 141 "name": name, 142 "ram": memoryMb, 143 "vcpus": cpu, 144 "disk": diskGB, 145 }, 146 } 147 resp, err := region.ecsPost("/flavors", params) 148 if err != nil { 149 return nil, errors.Wrap(err, "ecsPost") 150 } 151 flavor := &SFlavor{region: region} 152 err = resp.Unmarshal(flavor, "flavor") 153 if err != nil { 154 return nil, errors.Wrap(err, "resp.Unmarshal") 155 } 156 return flavor, nil 157 } 158 159 func (region *SRegion) DeleteFlavor(flavorId string) error { 160 _, err := region.ecsDelete("/flavors/" + flavorId) 161 return err 162 } 163 164 func (flavor *SFlavor) Delete() error { 165 return flavor.region.DeleteFlavor(flavor.Id) 166 } 167 168 func (flavor *SFlavor) IsEmulated() bool { 169 return false 170 } 171 172 func (flavor *SFlavor) Refresh() error { 173 _flavor, err := flavor.region.GetFlavor(flavor.Id) 174 if err != nil { 175 return err 176 } 177 return jsonutils.Update(flavor, _flavor) 178 } 179 180 func (flavor *SFlavor) GetName() string { 181 if len(flavor.OriginalName) > 0 { 182 return flavor.OriginalName 183 } 184 return flavor.Name 185 } 186 187 func (flavor *SFlavor) GetId() string { 188 return flavor.Id 189 } 190 191 func (flavor *SFlavor) GetGlobalId() string { 192 return flavor.Id 193 } 194 195 func (flavor *SFlavor) GetInstanceTypeFamily() string { 196 return api.InstanceFamilies[api.SkuCategoryGeneralPurpose] 197 } 198 199 func (flavor *SFlavor) GetInstanceTypeCategory() string { 200 return api.SkuCategoryGeneralPurpose 201 } 202 203 func (flavor *SFlavor) GetPrepaidStatus() string { 204 return api.SkuStatusSoldout 205 } 206 207 func (flavor *SFlavor) GetPostpaidStatus() string { 208 return api.SkuStatusAvailable 209 } 210 211 func (flavor *SFlavor) GetCpuArch() string { 212 return "" 213 } 214 215 func (flavor *SFlavor) GetCpuCoreCount() int { 216 return int(flavor.Vcpus) 217 } 218 219 func (flavor *SFlavor) GetMemorySizeMB() int { 220 return flavor.RAM 221 } 222 223 func (flavor *SFlavor) GetOsName() string { 224 return "Any" 225 } 226 227 func (flavor *SFlavor) GetSysDiskResizable() bool { 228 return true 229 } 230 231 func (flavor *SFlavor) GetSysDiskType() string { 232 return "" 233 } 234 235 func (flavor *SFlavor) GetSysDiskMinSizeGB() int { 236 return 0 237 } 238 239 func (flavor *SFlavor) GetSysDiskMaxSizeGB() int { 240 return flavor.Disk 241 } 242 243 func (flavor *SFlavor) GetAttachedDiskType() string { 244 return "iscsi" 245 } 246 247 func (flavor *SFlavor) GetAttachedDiskSizeGB() int { 248 return 0 249 } 250 251 func (flavor *SFlavor) GetAttachedDiskCount() int { 252 return 0 253 } 254 255 func (flavor *SFlavor) GetDataDiskTypes() string { 256 return "" 257 } 258 259 func (flavor *SFlavor) GetDataDiskMaxCount() int { 260 return 6 261 } 262 263 func (flavor *SFlavor) GetNicType() string { 264 return "vpc" 265 } 266 267 func (flavor *SFlavor) GetNicMaxCount() int { 268 return 1 269 } 270 271 func (flavor *SFlavor) GetGpuAttachable() bool { 272 return false 273 } 274 275 func (flavor *SFlavor) GetGpuSpec() string { 276 return "" 277 } 278 279 func (flavor *SFlavor) GetGpuCount() int { 280 return 0 281 } 282 283 func (flavor *SFlavor) GetGpuMaxCount() int { 284 return 0 285 }