| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- // Copyright 2019 Yunion
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package cloudpods
- import (
- "context"
- "fmt"
- "net/http"
- "strings"
- api "yunion.io/x/cloudmux/pkg/apis/compute"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- "yunion.io/x/jsonutils"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/printutils"
- "yunion.io/x/onecloud/pkg/mcclient"
- "yunion.io/x/onecloud/pkg/mcclient/modules"
- "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
- )
- const (
- CLOUD_PROVIDER_CLOUDPODS = api.CLOUD_PROVIDER_CLOUDPODS
- CLOUDPODS_DEFAULT_REGION = "default"
- )
- var (
- defaultParams map[string]interface{} = map[string]interface{}{
- "details": true,
- "show_emulated": true,
- "scope": "system",
- "cloud_env": "onpremise",
- }
- )
- type ModelManager interface {
- List(session *mcclient.ClientSession, params jsonutils.JSONObject) (*printutils.ListResult, error)
- Create(session *mcclient.ClientSession, params jsonutils.JSONObject) (jsonutils.JSONObject, error)
- Delete(session *mcclient.ClientSession, id string, param jsonutils.JSONObject) (jsonutils.JSONObject, error)
- DeleteWithParam(session *mcclient.ClientSession, id string, query jsonutils.JSONObject, body jsonutils.JSONObject) (jsonutils.JSONObject, error)
- PerformAction(session *mcclient.ClientSession, id string, action string, params jsonutils.JSONObject) (jsonutils.JSONObject, error)
- Get(session *mcclient.ClientSession, id string, params jsonutils.JSONObject) (jsonutils.JSONObject, error)
- Update(session *mcclient.ClientSession, id string, params jsonutils.JSONObject) (jsonutils.JSONObject, error)
- GetKeyword() string
- }
- type CloudpodsClientConfig struct {
- cpcfg cloudprovider.ProviderConfig
- authURL string
- region string
- accessKey string
- accessSecret string
- adminProjectId string
- debug bool
- }
- func NewCloudpodsClientConfig(authURL, accessKey, accessSecret string) *CloudpodsClientConfig {
- cfg := &CloudpodsClientConfig{
- authURL: authURL,
- accessKey: accessKey,
- accessSecret: accessSecret,
- }
- return cfg
- }
- func (cfg *CloudpodsClientConfig) Debug(debug bool) *CloudpodsClientConfig {
- cfg.debug = debug
- return cfg
- }
- func (cfg *CloudpodsClientConfig) CloudproviderConfig(cpcfg cloudprovider.ProviderConfig) *CloudpodsClientConfig {
- cfg.cpcfg = cpcfg
- return cfg
- }
- type SCloudpodsClient struct {
- *CloudpodsClientConfig
- s *mcclient.ClientSession
- }
- func (self *SCloudpodsClient) auth() error {
- client := mcclient.NewClient(self.authURL, 0, self.debug, true, "", "")
- client.SetHttpTransportProxyFunc(self.cpcfg.ProxyFunc)
- ts, _ := client.GetClient().Transport.(*http.Transport)
- client.SetTransport(cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response) error, error) {
- if self.cpcfg.ReadOnly {
- if req.Method == "GET" || req.Method == "HEAD" {
- return nil, nil
- }
- // 认证
- if req.Method == "POST" && req.URL.Path == "/v3/auth/tokens" {
- return nil, nil
- }
- return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path)
- }
- return nil, nil
- }))
- token, err := client.AuthenticateByAccessKey(self.accessKey, self.accessSecret, "cli")
- if err != nil {
- if errors.Cause(err) == cloudprovider.ErrUnauthorized {
- return errors.Wrapf(cloudprovider.ErrInvalidAccessKey, "%v", err)
- }
- return err
- }
- serviceRegion, endpoints := "", 0
- for _, region := range token.GetRegions() {
- if len(token.GetEndpoints(region, "")) > endpoints {
- serviceRegion = region
- }
- }
- endpoint := "publicURL"
- if strings.Contains(self.authURL, "api/s/identity/v3") {
- endpoint = "apigateway"
- }
- self.s = client.NewSession(context.Background(), serviceRegion, "", endpoint, token)
- if !self.s.GetToken().HasSystemAdminPrivilege() {
- return fmt.Errorf("no system admin privilege")
- }
- if self.s.GetProjectId() == self.adminProjectId {
- return fmt.Errorf("You can't manage yourself environment")
- }
- return nil
- }
- func NewCloudpodsClient(cfg *CloudpodsClientConfig) (*SCloudpodsClient, error) {
- cli := &SCloudpodsClient{
- CloudpodsClientConfig: cfg,
- }
- return cli, cli.auth()
- }
- func (self *SCloudpodsClient) GetRegion(regionId string) (*SRegion, error) {
- ret := &SRegion{cli: self}
- return ret, self.get(&compute.Cloudregions, regionId, nil, ret)
- }
- func (self *SCloudpodsClient) get(manager ModelManager, id string, params map[string]string, retVal interface{}) error {
- if len(id) == 0 {
- return errors.Wrap(cloudprovider.ErrNotFound, "empty id")
- }
- body := jsonutils.NewDict()
- for k, v := range params {
- body.Set(k, jsonutils.NewString(v))
- }
- resp, err := manager.Get(self.s, id, body)
- if err != nil {
- if strings.Contains(err.Error(), "NotFoundError") {
- return errors.Wrapf(cloudprovider.ErrNotFound, "%v", err)
- }
- return errors.Wrapf(err, "Get(%s)", id)
- }
- obj := resp.(*jsonutils.JSONDict)
- if manager.GetKeyword() == compute.Servers.GetKeyword() {
- obj.Remove("cdrom")
- }
- return obj.Unmarshal(retVal)
- }
- func (self *SCloudpodsClient) perform(manager ModelManager, id, action string, params interface{}) (jsonutils.JSONObject, error) {
- return manager.PerformAction(self.s, id, action, jsonutils.Marshal(params))
- }
- func (self *SCloudpodsClient) delete(manager ModelManager, id string) error {
- if len(id) == 0 {
- return nil
- }
- params := map[string]interface{}{"override_pending_delete": true}
- _, err := manager.DeleteWithParam(self.s, id, jsonutils.Marshal(params), nil)
- return err
- }
- func (self *SCloudpodsClient) update(manager ModelManager, id string, params interface{}) error {
- _, err := manager.Update(self.s, id, jsonutils.Marshal(params))
- return err
- }
- func (self *SCloudpodsClient) GetAccountId() string {
- return self.authURL
- }
- func (self *SCloudpodsClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
- return []cloudprovider.SSubAccount{
- {
- Name: self.cpcfg.Name,
- Account: self.cpcfg.Account,
- HealthStatus: api.CLOUD_PROVIDER_HEALTH_NORMAL,
- },
- }, nil
- }
- func (self *SCloudpodsClient) GetVersion() string {
- version, err := modules.GetVersion(self.s, "compute_v2")
- if err != nil {
- return ""
- }
- return version
- }
- func (self *SCloudpodsClient) create(manager ModelManager, params interface{}, retVal interface{}) error {
- resp, err := manager.Create(self.s, jsonutils.Marshal(params))
- if err != nil {
- return err
- }
- obj := resp.(*jsonutils.JSONDict)
- if manager.GetKeyword() == compute.Servers.GetKeyword() {
- obj.Remove("cdrom")
- }
- return obj.Unmarshal(retVal)
- }
- func (self *SCloudpodsClient) list(manager ModelManager, params map[string]interface{}, retVal interface{}) error {
- if params == nil {
- params = map[string]interface{}{}
- }
- for k, v := range defaultParams {
- if _, ok := params[k]; !ok {
- params[k] = v
- }
- }
- ret := []jsonutils.JSONObject{}
- for {
- params["offset"] = len(ret)
- part, err := manager.List(self.s, jsonutils.Marshal(params))
- if err != nil {
- return errors.Wrapf(err, "list")
- }
- for i := range part.Data {
- data := part.Data[i].(*jsonutils.JSONDict)
- if manager.GetKeyword() == compute.Servers.GetKeyword() {
- data.Remove("cdrom")
- }
- ret = append(ret, data)
- }
- if len(ret) >= part.Total {
- break
- }
- }
- return jsonutils.Update(retVal, ret)
- }
- func (self *SCloudpodsClient) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) {
- regions, err := self.GetRegions()
- if err != nil {
- return nil, err
- }
- for i := range regions {
- regions[i].cli = self
- if regions[i].GetGlobalId() == id {
- return ®ions[i], nil
- }
- }
- return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", id)
- }
- func (self *SCloudpodsClient) GetIRegions() ([]cloudprovider.ICloudRegion, error) {
- regions, err := self.GetRegions()
- if err != nil {
- return nil, err
- }
- ret := []cloudprovider.ICloudRegion{}
- for i := range regions {
- regions[i].cli = self
- ret = append(ret, ®ions[i])
- }
- return ret, nil
- }
- func (self *SCloudpodsClient) GetRegions() ([]SRegion, error) {
- ret := []SRegion{}
- return ret, self.list(&compute.Cloudregions, nil, &ret)
- }
- func (self *SCloudpodsClient) GetCloudRegionExternalIdPrefix() string {
- return fmt.Sprintf("%s/%s", api.CLOUD_PROVIDER_CLOUDPODS, self.cpcfg.Id)
- }
- func (self *SCloudpodsClient) GetCapabilities() []string {
- return []string{
- cloudprovider.CLOUD_CAPABILITY_PROJECT + cloudprovider.READ_ONLY_SUFFIX,
- cloudprovider.CLOUD_CAPABILITY_COMPUTE,
- cloudprovider.CLOUD_CAPABILITY_NETWORK,
- cloudprovider.CLOUD_CAPABILITY_SECURITY_GROUP,
- cloudprovider.CLOUD_CAPABILITY_EIP,
- }
- }
|