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  }