yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/openstack/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 "strings" 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/onecloud/pkg/httperrors" 28 "yunion.io/x/onecloud/pkg/mcclient" 29 "yunion.io/x/cloudmux/pkg/multicloud/openstack" 30 ) 31 32 type SOpenStackProviderFactory struct { 33 cloudprovider.SPrivateCloudBaseProviderFactory 34 } 35 36 var EndpointTypes = []string{"admin", "internal", "public"} 37 38 func (self *SOpenStackProviderFactory) GetId() string { 39 return openstack.CLOUD_PROVIDER_OPENSTACK 40 } 41 42 func (self *SOpenStackProviderFactory) GetName() string { 43 return openstack.CLOUD_PROVIDER_OPENSTACK 44 } 45 46 func (self *SOpenStackProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, input cloudprovider.SCloudaccountCredential) (cloudprovider.SCloudaccount, error) { 47 output := cloudprovider.SCloudaccount{} 48 if len(input.ProjectName) == 0 { 49 return output, errors.Wrap(httperrors.ErrMissingParameter, "project_name") 50 } 51 if len(input.Username) == 0 { 52 return output, errors.Wrap(httperrors.ErrMissingParameter, "username") 53 } 54 if len(input.Password) == 0 { 55 return output, errors.Wrap(httperrors.ErrMissingParameter, "password") 56 } 57 if len(input.AuthUrl) == 0 { 58 return output, errors.Wrap(httperrors.ErrMissingParameter, "auth_url") 59 } 60 61 output.Account = fmt.Sprintf("%s/%s", input.ProjectName, input.Username) 62 if len(input.DomainName) > 0 { 63 output.Account = fmt.Sprintf("%s/%s", output.Account, input.DomainName) 64 } 65 66 output.Secret = input.Password 67 output.AccessUrl = input.AuthUrl 68 return output, nil 69 } 70 71 func (self *SOpenStackProviderFactory) ValidateUpdateCloudaccountCredential(ctx context.Context, userCred mcclient.TokenCredential, input cloudprovider.SCloudaccountCredential, cloudaccount string) (cloudprovider.SCloudaccount, error) { 72 output := cloudprovider.SCloudaccount{} 73 if len(input.ProjectName) == 0 { 74 accountInfo := strings.Split(cloudaccount, "/") 75 if len(accountInfo) < 2 { 76 return output, errors.Wrap(httperrors.ErrMissingParameter, "project_name") 77 } 78 input.ProjectName = accountInfo[0] 79 } 80 if len(input.Username) == 0 { 81 return output, errors.Wrap(httperrors.ErrMissingParameter, "username") 82 } 83 if len(input.Password) == 0 { 84 return output, errors.Wrap(httperrors.ErrMissingParameter, "password") 85 } 86 87 _account := fmt.Sprintf("%s/%s", input.ProjectName, input.Username) 88 if len(input.DomainName) == 0 { 89 if accountInfo := strings.Split(cloudaccount, "/"); len(accountInfo) == 3 { 90 input.DomainName = accountInfo[2] 91 } 92 } 93 94 if len(input.DomainName) > 0 { 95 _account = fmt.Sprintf("%s/%s", _account, input.DomainName) 96 } 97 98 output = cloudprovider.SCloudaccount{ 99 Account: _account, 100 Secret: input.Password, 101 } 102 return output, nil 103 } 104 105 func (self *SOpenStackProviderFactory) IsNeedForceAutoCreateProject() bool { 106 return true 107 } 108 109 func (self *SOpenStackProviderFactory) GetProvider(cfg cloudprovider.ProviderConfig) (cloudprovider.ICloudProvider, error) { 110 accountInfo := strings.Split(cfg.Account, "/") 111 if len(accountInfo) < 2 { 112 return nil, fmt.Errorf("Missing username or project name %s", cfg.Account) 113 } 114 project, username, endpointType, domainName, projectDomainName := accountInfo[0], accountInfo[1], "internal", "Default", "Default" 115 if len(accountInfo) == 3 { 116 domainName, projectDomainName = accountInfo[2], accountInfo[2] 117 } 118 client, err := openstack.NewOpenStackClient( 119 openstack.NewOpenstackClientConfig( 120 cfg.URL, 121 username, 122 cfg.Secret, 123 project, 124 projectDomainName, 125 ). 126 DomainName(domainName). 127 EndpointType(endpointType). 128 CloudproviderConfig(cfg), 129 ) 130 if err != nil { 131 return nil, err 132 } 133 return &SOpenStackProvider{ 134 SBaseProvider: cloudprovider.NewBaseProvider(self), 135 client: client, 136 }, nil 137 } 138 139 func (self *SOpenStackProviderFactory) GetClientRC(info cloudprovider.SProviderInfo) (map[string]string, error) { 140 accountInfo := strings.Split(info.Account, "/") 141 if len(accountInfo) < 2 { 142 return nil, fmt.Errorf("Missing username or project name %s", info.Account) 143 } 144 project, username, endpointType, domainName, projectDomainName := accountInfo[0], accountInfo[1], "internal", "Default", "Default" 145 if len(accountInfo) == 3 { 146 domainName, projectDomainName = accountInfo[2], accountInfo[2] 147 } 148 149 return map[string]string{ 150 "OPENSTACK_AUTH_URL": info.Url, 151 "OPENSTACK_USERNAME": username, 152 "OPENSTACK_PASSWORD": info.Secret, 153 "OPENSTACK_PROJECT": project, 154 "OPENSTACK_ENDPOINT_TYPE": endpointType, 155 "OPENSTACK_DOMAIN_NAME": domainName, 156 "OPENSTACK_PROJECT_DOMAIN": projectDomainName, 157 "OPENSTACK_REGION_ID": openstack.OPENSTACK_DEFAULT_REGION, 158 }, nil 159 } 160 161 func init() { 162 factory := SOpenStackProviderFactory{} 163 cloudprovider.RegisterFactory(&factory) 164 } 165 166 type SOpenStackProvider struct { 167 cloudprovider.SBaseProvider 168 client *openstack.SOpenStackClient 169 } 170 171 func (self *SOpenStackProvider) GetVersion() string { 172 return "" 173 } 174 175 func (self *SOpenStackProvider) GetSysInfo() (jsonutils.JSONObject, error) { 176 return jsonutils.NewDict(), nil 177 } 178 179 func (self *SOpenStackProvider) GetSubAccounts() ([]cloudprovider.SSubAccount, error) { 180 return self.client.GetSubAccounts() 181 } 182 183 func (self *SOpenStackProvider) GetAccountId() string { 184 return "" 185 } 186 187 func (self *SOpenStackProvider) GetIRegions() []cloudprovider.ICloudRegion { 188 return self.client.GetIRegions() 189 } 190 191 func (self *SOpenStackProvider) GetIRegionById(extId string) (cloudprovider.ICloudRegion, error) { 192 return self.client.GetIRegionById(extId) 193 } 194 195 func (self *SOpenStackProvider) GetBalance() (float64, string, error) { 196 return 0.0, api.CLOUD_PROVIDER_HEALTH_UNKNOWN, cloudprovider.ErrNotSupported 197 } 198 199 func (self *SOpenStackProvider) GetCloudRegionExternalIdPrefix() string { 200 return self.client.GetCloudRegionExternalIdPrefix() 201 } 202 203 func (self *SOpenStackProvider) GetIProjects() ([]cloudprovider.ICloudProject, error) { 204 return self.client.GetIProjects() 205 } 206 207 func (self *SOpenStackProvider) CreateIProject(name string) (cloudprovider.ICloudProject, error) { 208 return self.client.CreateIProject(name) 209 } 210 211 func (self *SOpenStackProvider) GetStorageClasses(regionId string) []string { 212 return nil 213 } 214 215 func (self *SOpenStackProvider) GetBucketCannedAcls(regionId string) []string { 216 return nil 217 } 218 219 func (self *SOpenStackProvider) GetObjectCannedAcls(regionId string) []string { 220 return nil 221 } 222 223 func (self *SOpenStackProvider) GetCapabilities() []string { 224 return self.client.GetCapabilities() 225 }