yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/openstack/zone.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  	"strings"
    20  	"time"
    21  
    22  	"yunion.io/x/jsonutils"
    23  	"yunion.io/x/pkg/errors"
    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 ZoneState struct {
    31  	Available bool
    32  }
    33  
    34  type HostState struct {
    35  	Available bool
    36  	Active    bool
    37  	UpdatedAt time.Time
    38  }
    39  
    40  type SZone struct {
    41  	multicloud.SResourceBase
    42  	OpenStackTags
    43  	region *SRegion
    44  
    45  	ZoneName  string
    46  	ZoneState ZoneState
    47  
    48  	Hosts map[string]jsonutils.JSONObject
    49  
    50  	hosts []SHypervisor
    51  }
    52  
    53  func (zone *SZone) GetId() string {
    54  	return zone.ZoneName
    55  }
    56  
    57  func (zone *SZone) GetName() string {
    58  	return zone.ZoneName
    59  }
    60  
    61  func (zone *SZone) GetI18n() cloudprovider.SModelI18nTable {
    62  	table := cloudprovider.SModelI18nTable{}
    63  	table["name"] = cloudprovider.NewSModelI18nEntry(zone.GetName()).CN(zone.GetName())
    64  	return table
    65  }
    66  
    67  func (zone *SZone) GetGlobalId() string {
    68  	return fmt.Sprintf("%s/%s/%s", CLOUD_PROVIDER_OPENSTACK, zone.region.Name, zone.ZoneName)
    69  }
    70  
    71  func (zone *SZone) IsEmulated() bool {
    72  	return false
    73  }
    74  
    75  func (zone *SZone) GetStatus() string {
    76  	if zone.ZoneState.Available {
    77  		return api.ZONE_ENABLE
    78  	}
    79  	return api.ZONE_DISABLE
    80  }
    81  
    82  func (zone *SZone) Refresh() error {
    83  	// do nothing
    84  	return nil
    85  }
    86  
    87  func (zone *SZone) GetIRegion() cloudprovider.ICloudRegion {
    88  	return zone.region
    89  }
    90  
    91  func (zone *SZone) getStorageByCategory(category, host string) (*SStorage, error) {
    92  	storages, err := zone.region.GetStorageTypes()
    93  	if err != nil {
    94  		return nil, errors.Wrap(err, "GetStorageTypes")
    95  	}
    96  	for i := range storages {
    97  		if storages[i].Name == category || storages[i].ExtraSpecs.VolumeBackendName == category {
    98  			storages[i].zone = zone
    99  			return &storages[i], nil
   100  		}
   101  	}
   102  	for i := range storages {
   103  		if strings.HasSuffix(host, "#"+storages[i].Name) || strings.HasSuffix(host, "#"+storages[i].ExtraSpecs.VolumeBackendName) {
   104  			storages[i].zone = zone
   105  			return &storages[i], nil
   106  		}
   107  	}
   108  	return nil, fmt.Errorf("No such storage [%s]", category)
   109  }
   110  
   111  func (zone *SZone) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
   112  	storages, err := zone.region.GetStorageTypes()
   113  	if err != nil && errors.Cause(err) != ErrNoEndpoint {
   114  		return nil, errors.Wrap(err, "GetStorageTypes")
   115  	}
   116  	istorages := []cloudprovider.ICloudStorage{}
   117  	for i := range storages {
   118  		storages[i].zone = zone
   119  		istorages = append(istorages, &storages[i])
   120  	}
   121  	err = zone.fetchHosts()
   122  	if err != nil {
   123  		return nil, errors.Wrap(err, "fetchHosts")
   124  	}
   125  	for i := range zone.hosts {
   126  		nova := &SNovaStorage{host: &zone.hosts[i], zone: zone}
   127  		istorages = append(istorages, nova)
   128  	}
   129  	return istorages, nil
   130  }
   131  
   132  func (zone *SZone) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
   133  	istorages, err := zone.GetIStorages()
   134  	if err != nil {
   135  		return nil, errors.Wrap(err, "GetIStorages")
   136  	}
   137  	for i := 0; i < len(istorages); i++ {
   138  		if istorages[i].GetGlobalId() == id {
   139  			return istorages[i], nil
   140  		}
   141  	}
   142  	return nil, cloudprovider.ErrNotFound
   143  }
   144  
   145  func (zone *SZone) fetchHosts() error {
   146  	if len(zone.hosts) > 0 {
   147  		return nil
   148  	}
   149  
   150  	zone.hosts = []SHypervisor{}
   151  	hypervisors, err := zone.region.GetHypervisors()
   152  	if err != nil {
   153  		return errors.Wrap(err, "GetHypervisors")
   154  	}
   155  	for i := range hypervisors {
   156  		hypervisor := strings.ToLower(hypervisors[i].HypervisorType)
   157  		// 过滤vmware的机器
   158  		if strings.Index(hypervisor, "vmware") != -1 {
   159  			continue
   160  		}
   161  
   162  		_, ok1 := zone.Hosts[hypervisors[i].HypervisorHostname]
   163  		_, ok2 := zone.Hosts[hypervisors[i].Service.Host]
   164  		if !ok1 && !ok2 {
   165  			continue
   166  		}
   167  		zone.hosts = append(zone.hosts, hypervisors[i])
   168  	}
   169  	return nil
   170  
   171  }
   172  
   173  func (zone *SZone) GetIHosts() ([]cloudprovider.ICloudHost, error) {
   174  	err := zone.fetchHosts()
   175  	if err != nil {
   176  		return nil, errors.Wrap(err, "fetchHosts")
   177  	}
   178  	ihosts := []cloudprovider.ICloudHost{}
   179  	for i := range zone.hosts {
   180  		zone.hosts[i].zone = zone
   181  		ihosts = append(ihosts, &zone.hosts[i])
   182  	}
   183  	return ihosts, nil
   184  }
   185  
   186  func (zone *SZone) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
   187  	ihosts, err := zone.GetIHosts()
   188  	if err != nil {
   189  		return nil, errors.Wrap(err, "GetIHosts")
   190  	}
   191  	for i := range ihosts {
   192  		if ihosts[i].GetGlobalId() == id {
   193  			return ihosts[i], nil
   194  		}
   195  	}
   196  	return nil, cloudprovider.ErrNotFound
   197  }
   198  
   199  func (region *SRegion) getZones() ([]SZone, error) {
   200  	zones := []SZone{}
   201  	resp, err := region.ecsList("os-availability-zone/detail", nil)
   202  	if err != nil {
   203  		return nil, errors.Wrap(err, "ecsList.os-availability-zone")
   204  	}
   205  	err = resp.Unmarshal(&zones, "availabilityZoneInfo")
   206  	if err != nil {
   207  		return nil, errors.Wrap(err, "resp.Unmarshal")
   208  	}
   209  	return zones, nil
   210  }