yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/esxi/provider/provider.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 provider 16 17 import ( 18 "context" 19 "fmt" 20 "net/url" 21 "strconv" 22 "strings" 23 24 "yunion.io/x/jsonutils" 25 "yunion.io/x/log" 26 "yunion.io/x/pkg/errors" 27 "yunion.io/x/pkg/util/regutils" 28 29 api "yunion.io/x/cloudmux/pkg/apis/compute" 30 "yunion.io/x/cloudmux/pkg/cloudprovider" 31 "yunion.io/x/onecloud/pkg/httperrors" 32 "yunion.io/x/onecloud/pkg/mcclient" 33 "yunion.io/x/cloudmux/pkg/multicloud/esxi" 34 ) 35 36 type SESXiProviderFactory struct { 37 cloudprovider.SPremiseBaseProviderFactory 38 } 39 40 func (self *SESXiProviderFactory) GetId() string { 41 return esxi.CLOUD_PROVIDER_VMWARE 42 } 43 44 func (self *SESXiProviderFactory) GetName() string { 45 return esxi.CLOUD_PROVIDER_VMWARE 46 } 47 48 func (self *SESXiProviderFactory) ValidateChangeBandwidth(instanceId string, bandwidth int64) error { 49 return fmt.Errorf("Changing %s bandwidth is not supported", esxi.CLOUD_PROVIDER_VMWARE) 50 } 51 52 func (self *SESXiProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, input cloudprovider.SCloudaccountCredential) (cloudprovider.SCloudaccount, error) { 53 output := cloudprovider.SCloudaccount{} 54 if len(input.Username) == 0 { 55 return output, errors.Wrap(httperrors.ErrMissingParameter, "username") 56 } 57 if len(input.Password) == 0 { 58 return output, errors.Wrap(httperrors.ErrMissingParameter, "password") 59 } 60 if len(input.Host) == 0 { 61 return output, errors.Wrap(httperrors.ErrMissingParameter, "host") 62 } 63 if !regutils.MatchIPAddr(input.Host) && !regutils.MatchDomainName(input.Host) { 64 return output, errors.Wrap(httperrors.ErrInputParameter, "host should be ip or domain name") 65 } 66 output.AccessUrl = fmt.Sprintf("https://%s:%d/sdk", input.Host, input.Port) 67 if input.Port == 0 || input.Port == 443 { 68 output.AccessUrl = fmt.Sprintf("https://%s/sdk", input.Host) 69 } 70 output.Account = input.Username 71 output.Secret = input.Password 72 return output, nil 73 } 74 75 func (self *SESXiProviderFactory) ValidateUpdateCloudaccountCredential(ctx context.Context, userCred mcclient.TokenCredential, input cloudprovider.SCloudaccountCredential, cloudaccount string) (cloudprovider.SCloudaccount, error) { 76 output := cloudprovider.SCloudaccount{} 77 if len(input.Username) == 0 { 78 return output, errors.Wrap(httperrors.ErrMissingParameter, "username") 79 } 80 if len(input.Password) == 0 { 81 return output, errors.Wrap(httperrors.ErrMissingParameter, "password") 82 } 83 output = cloudprovider.SCloudaccount{ 84 Account: input.Username, 85 Secret: input.Password, 86 } 87 return output, nil 88 } 89 90 func parseHostPort(host string, defPort int) (string, int, error) { 91 colonPos := strings.IndexByte(host, ':') 92 if colonPos > 0 { 93 h := host[:colonPos] 94 p, err := strconv.Atoi(host[colonPos+1:]) 95 if err != nil { 96 log.Errorf("Invalid host %s", host) 97 return "", 0, err 98 } 99 if p == 0 { 100 p = defPort 101 } 102 return h, p, nil 103 } else { 104 return host, defPort, nil 105 } 106 } 107 108 func (self *SESXiProviderFactory) GetProvider(cfg cloudprovider.ProviderConfig) (cloudprovider.ICloudProvider, error) { 109 parts, err := url.Parse(cfg.URL) 110 if err != nil { 111 return nil, err 112 } 113 host, port, err := parseHostPort(parts.Host, 443) 114 if err != nil { 115 return nil, err 116 } 117 118 client, err := esxi.NewESXiClient( 119 esxi.NewESXiClientConfig( 120 host, port, cfg.Account, cfg.Secret, 121 ).CloudproviderConfig(cfg), 122 ) 123 if err != nil { 124 return nil, err 125 } 126 return &SESXiProvider{ 127 SBaseProvider: cloudprovider.NewBaseProvider(self), 128 client: client, 129 }, nil 130 } 131 132 func (self *SESXiProviderFactory) GetClientRC(info cloudprovider.SProviderInfo) (map[string]string, error) { 133 parts, err := url.Parse(info.Url) 134 if err != nil { 135 return nil, err 136 } 137 host, port, err := parseHostPort(parts.Host, 443) 138 if err != nil { 139 return nil, err 140 } 141 142 return map[string]string{ 143 "VMWARE_HOST": host, 144 "VMWARE_PORT": fmt.Sprintf("%d", port), 145 "VMWARE_ACCOUNT": info.Account, 146 "VMWARE_PASSWORD": info.Secret, 147 }, nil 148 } 149 150 func (self *SESXiProviderFactory) GetAccountIdEqualizer() func(origin, now string) bool { 151 return func(origin, now string) bool { 152 if len(now) == 0 { 153 return true 154 } 155 originUserName, nowUserName := origin, now 156 index1 := strings.Index(origin, "@") 157 index2 := strings.Index(now, "@") 158 if index1 != -1 { 159 originUserName = originUserName[:index1] 160 } 161 if index2 != -1 { 162 nowUserName = nowUserName[:index2] 163 } 164 return originUserName == nowUserName 165 } 166 } 167 168 func init() { 169 factory := SESXiProviderFactory{} 170 cloudprovider.RegisterFactory(&factory) 171 } 172 173 type SESXiProvider struct { 174 cloudprovider.SBaseProvider 175 client *esxi.SESXiClient 176 } 177 178 func (self *SESXiProvider) GetSysInfo() (jsonutils.JSONObject, error) { 179 return self.client.About(), nil 180 } 181 182 func (self *SESXiProvider) GetVersion() string { 183 return self.client.GetVersion() 184 } 185 186 func (self *SESXiProvider) GetSubAccounts() ([]cloudprovider.SSubAccount, error) { 187 return self.client.GetSubAccounts() 188 } 189 190 func (self *SESXiProvider) GetAccountId() string { 191 return self.client.GetAccountId() 192 } 193 194 func (self *SESXiProvider) GetIRegions() []cloudprovider.ICloudRegion { 195 return nil 196 } 197 198 func (self *SESXiProvider) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) { 199 return nil, cloudprovider.ErrNotSupported 200 } 201 202 func (self *SESXiProvider) GetBalance() (float64, string, error) { 203 return 0.0, api.CLOUD_PROVIDER_HEALTH_NORMAL, cloudprovider.ErrNotSupported 204 } 205 206 func (self *SESXiProvider) GetOnPremiseIRegion() (cloudprovider.ICloudRegion, error) { 207 return self.client, nil 208 } 209 210 func (self *SESXiProvider) GetIProjects() ([]cloudprovider.ICloudProject, error) { 211 return self.client.GetIProjects() 212 } 213 214 func (self *SESXiProvider) GetStorageClasses(regionId string) []string { 215 return nil 216 } 217 218 func (self *SESXiProvider) GetBucketCannedAcls(regionId string) []string { 219 return nil 220 } 221 222 func (self *SESXiProvider) GetObjectCannedAcls(regionId string) []string { 223 return nil 224 } 225 226 func (self *SESXiProvider) GetCapabilities() []string { 227 return self.client.GetCapabilities() 228 } 229 230 func (self *SESXiProvider) GetMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) { 231 return self.client.GetMetrics(opts) 232 }