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 }