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 }