yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/openstack/hypervisor.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  	"strconv"
    21  
    22  	"yunion.io/x/jsonutils"
    23  	"yunion.io/x/pkg/errors"
    24  	"yunion.io/x/pkg/utils"
    25  
    26  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    27  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    28  	"yunion.io/x/cloudmux/pkg/multicloud"
    29  )
    30  
    31  type CpuInfo struct {
    32  	Arch     string
    33  	Model    string
    34  	Vendor   string
    35  	Feature  []string
    36  	Topology map[string]int
    37  }
    38  
    39  type Service struct {
    40  	Host           string
    41  	ID             string
    42  	DisabledReason string
    43  }
    44  
    45  type SResource struct {
    46  	CPU      int
    47  	DiskGB   int
    48  	Host     string
    49  	MemoryMb int
    50  	Project  string
    51  }
    52  
    53  type SHypervisor struct {
    54  	multicloud.SHostBase
    55  	zone *SZone
    56  
    57  	CpuInfo string
    58  
    59  	Aggregates         []string
    60  	CurrentWorkload    int
    61  	Status             string
    62  	State              string
    63  	DiskAvailableLeast int
    64  	HostIP             string
    65  	FreeDiskGB         int
    66  	FreeRamMB          int
    67  	HypervisorHostname string
    68  	HypervisorType     string
    69  	HypervisorVersion  string
    70  	Id                 string
    71  	LocalGB            int
    72  	LocalGbUsed        int
    73  	MemoryMB           int
    74  	MemoryMbUsed       int
    75  	RunningVms         int
    76  	Service            Service
    77  	Vcpus              int
    78  	VcpusUsed          int8
    79  }
    80  
    81  func (host *SHypervisor) GetId() string {
    82  	return host.Id
    83  }
    84  
    85  func (host *SHypervisor) GetName() string {
    86  	if len(host.HypervisorHostname) > 0 {
    87  		return host.HypervisorHostname
    88  	}
    89  	return host.Service.Host
    90  }
    91  
    92  func (host *SHypervisor) GetGlobalId() string {
    93  	return host.GetId()
    94  }
    95  
    96  func (host *SHypervisor) GetIWires() ([]cloudprovider.ICloudWire, error) {
    97  	vpcs, err := host.zone.region.GetIVpcs()
    98  	if err != nil {
    99  		return nil, errors.Wrapf(err, "GetIVpc")
   100  	}
   101  	ret := []cloudprovider.ICloudWire{}
   102  	for i := range vpcs {
   103  		iwires, err := vpcs[i].GetIWires()
   104  		if err != nil {
   105  			return nil, errors.Wrapf(err, "GetIWires")
   106  		}
   107  		ret = append(ret, iwires...)
   108  	}
   109  	return ret, nil
   110  }
   111  
   112  func (host *SHypervisor) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
   113  	istorages := []cloudprovider.ICloudStorage{}
   114  	storages, err := host.zone.region.GetStorageTypes()
   115  	if err != nil && errors.Cause(err) != ErrNoEndpoint {
   116  		return nil, errors.Wrap(err, "GetStorageTypes")
   117  	}
   118  	for i := range storages {
   119  		storages[i].zone = host.zone
   120  		istorages = append(istorages, &storages[i])
   121  	}
   122  	nova := &SNovaStorage{host: host, zone: host.zone}
   123  	istorages = append(istorages, nova)
   124  	return istorages, nil
   125  }
   126  
   127  func (host *SHypervisor) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
   128  	return host.zone.GetIStorageById(id)
   129  }
   130  
   131  func (host *SHypervisor) GetIVMs() ([]cloudprovider.ICloudVM, error) {
   132  	instances, err := host.zone.region.GetInstances(host.HypervisorHostname)
   133  	if err != nil {
   134  		return nil, err
   135  	}
   136  	iVMs := []cloudprovider.ICloudVM{}
   137  	for i := 0; i < len(instances); i++ {
   138  		instances[i].host = host
   139  		iVMs = append(iVMs, &instances[i])
   140  	}
   141  	return iVMs, nil
   142  }
   143  
   144  func (host *SHypervisor) GetIVMById(gid string) (cloudprovider.ICloudVM, error) {
   145  	instance, err := host.zone.region.GetInstance(gid)
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  	instance.host = host
   150  	return instance, nil
   151  }
   152  
   153  func (host *SHypervisor) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
   154  	instance, err := host.zone.CreateVM(host.Service.Host, desc)
   155  	if err != nil {
   156  		return nil, errors.Wrap(err, "CreateVM")
   157  	}
   158  	instance.host = host
   159  	return instance, nil
   160  }
   161  
   162  func (host *SHypervisor) GetEnabled() bool {
   163  	switch host.Status {
   164  	case "enabled", "":
   165  		return true
   166  	default:
   167  		return false
   168  	}
   169  }
   170  
   171  func (host *SHypervisor) GetAccessIp() string {
   172  	return host.HostIP
   173  }
   174  
   175  func (host *SHypervisor) GetAccessMac() string {
   176  	return ""
   177  }
   178  
   179  func (host *SHypervisor) GetSysInfo() jsonutils.JSONObject {
   180  	info := jsonutils.NewDict()
   181  	info.Add(jsonutils.NewString(CLOUD_PROVIDER_OPENSTACK), "manufacture")
   182  	return info
   183  }
   184  
   185  func (host *SHypervisor) GetSN() string {
   186  	return ""
   187  }
   188  
   189  func (host *SHypervisor) GetCpuCmtbound() float32 {
   190  	aggregates, err := host.zone.region.GetAggregates()
   191  	if err != nil || len(aggregates) == 0 {
   192  		return 16.0
   193  	}
   194  	CpuCmtbound := 1000000.0
   195  	for _, aggregate := range aggregates {
   196  		if utils.IsInStringArray(host.GetName(), aggregate.Hosts) {
   197  			if _cmtbound, ok := aggregate.Metadata["cpu_allocation_ratio"]; ok {
   198  				cmtbound, err := strconv.ParseFloat(_cmtbound, 32)
   199  				if err == nil && CpuCmtbound > cmtbound {
   200  					CpuCmtbound = cmtbound
   201  				}
   202  			}
   203  		}
   204  	}
   205  	if CpuCmtbound >= 1000000.0 {
   206  		return 16.0
   207  	}
   208  	return float32(CpuCmtbound)
   209  }
   210  
   211  func (host *SHypervisor) GetMemCmtbound() float32 {
   212  	aggregates, err := host.zone.region.GetAggregates()
   213  	if err != nil || len(aggregates) == 0 {
   214  		return 1.5
   215  	}
   216  	MemCmtbound := 1000000.0
   217  	for _, aggregate := range aggregates {
   218  		if utils.IsInStringArray(host.GetName(), aggregate.Hosts) {
   219  			if _cmtbound, ok := aggregate.Metadata["ram_allocation_ratio"]; ok {
   220  				cmtbound, err := strconv.ParseFloat(_cmtbound, 32)
   221  				if err == nil && MemCmtbound > cmtbound {
   222  					MemCmtbound = cmtbound
   223  				}
   224  			}
   225  		}
   226  	}
   227  	if MemCmtbound >= 1000000.0 {
   228  		return 1.5
   229  	}
   230  	return float32(MemCmtbound)
   231  }
   232  
   233  func (host *SHypervisor) GetCpuCount() int {
   234  	if host.Vcpus > 0 {
   235  		return host.Vcpus
   236  	}
   237  	host.Refresh()
   238  	return host.Vcpus
   239  }
   240  
   241  func (host *SHypervisor) GetNodeCount() int8 {
   242  	if len(host.CpuInfo) > 0 {
   243  		info, err := jsonutils.Parse([]byte(host.CpuInfo))
   244  		if err == nil {
   245  			cpuInfo := &CpuInfo{}
   246  			err = info.Unmarshal(cpuInfo)
   247  			if err == nil {
   248  				if cell, ok := cpuInfo.Topology["cells"]; ok {
   249  					return int8(cell)
   250  				}
   251  			}
   252  		}
   253  	}
   254  	return int8(host.GetCpuCount())
   255  }
   256  
   257  func (host *SHypervisor) GetCpuDesc() string {
   258  	return host.CpuInfo
   259  }
   260  
   261  func (host *SHypervisor) GetCpuMhz() int {
   262  	return 0
   263  }
   264  
   265  func (host *SHypervisor) GetMemSizeMB() int {
   266  	if host.MemoryMB > 0 {
   267  		return host.MemoryMB
   268  	}
   269  	host.Refresh()
   270  	return host.MemoryMB
   271  }
   272  
   273  func (host *SHypervisor) GetStorageSizeMB() int {
   274  	return host.LocalGB * 1024
   275  }
   276  
   277  func (host *SHypervisor) GetStorageType() string {
   278  	return api.DISK_TYPE_HYBRID
   279  }
   280  
   281  func (host *SHypervisor) GetHostType() string {
   282  	return api.HOST_TYPE_OPENSTACK
   283  }
   284  
   285  func (host *SHypervisor) GetHostStatus() string {
   286  	switch host.State {
   287  	case "up", "":
   288  		return api.HOST_ONLINE
   289  	default:
   290  		return api.HOST_OFFLINE
   291  	}
   292  }
   293  
   294  func (host *SHypervisor) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) {
   295  	return nil, cloudprovider.ErrNotSupported
   296  }
   297  
   298  func (host *SHypervisor) GetIsMaintenance() bool {
   299  	return false
   300  }
   301  
   302  func (host *SHypervisor) GetVersion() string {
   303  	version, _ := host.zone.region.GetMaxVersion(OPENSTACK_SERVICE_COMPUTE)
   304  	return version
   305  }
   306  
   307  func (host *SHypervisor) GetStatus() string {
   308  	return api.HOST_STATUS_RUNNING
   309  }
   310  
   311  func (host *SHypervisor) IsEmulated() bool {
   312  	return false
   313  }
   314  
   315  func (host *SHypervisor) Refresh() error {
   316  	return nil
   317  }
   318  
   319  func (region *SRegion) GetHypervisors() ([]SHypervisor, error) {
   320  	hypervisors := []SHypervisor{}
   321  	resource := "/os-hypervisors/detail"
   322  	query := url.Values{}
   323  	for {
   324  		resp, err := region.ecsList(resource, query)
   325  		if err != nil {
   326  			return nil, errors.Wrap(err, "ecsList")
   327  		}
   328  
   329  		part := struct {
   330  			Hypervisors      []SHypervisor
   331  			HypervisorsLinks SNextLinks
   332  		}{}
   333  
   334  		err = resp.Unmarshal(&part)
   335  		if err != nil {
   336  			return nil, errors.Wrap(err, "resp.Unmarshal")
   337  		}
   338  		hypervisors = append(hypervisors, part.Hypervisors...)
   339  		marker := part.HypervisorsLinks.GetNextMark()
   340  		if len(marker) == 0 {
   341  			break
   342  		}
   343  		query.Set("marker", marker)
   344  	}
   345  	return hypervisors, nil
   346  }
   347  
   348  func (region *SRegion) GetHypervisor(id string) (*SHypervisor, error) {
   349  	resource := fmt.Sprintf("/os-hypervisors/%s", id)
   350  	resp, err := region.ecsGet(resource)
   351  	if err != nil {
   352  		return nil, errors.Wrap(err, "ecsGet")
   353  	}
   354  	hypervisor := &SHypervisor{}
   355  	err = resp.Unmarshal(hypervisor, "hypervisor")
   356  	if err != nil {
   357  		return nil, errors.Wrap(err, "resp.Unmarshal")
   358  	}
   359  	return hypervisor, nil
   360  }