yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aliyun/access_groups.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 aliyun
    16  
    17  import (
    18  	"fmt"
    19  	"strings"
    20  
    21  	alierr "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors"
    22  
    23  	"yunion.io/x/pkg/errors"
    24  
    25  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    26  )
    27  
    28  type SAccessGroup struct {
    29  	region *SRegion
    30  
    31  	RuleCount        int
    32  	AccessGroupType  string
    33  	Description      string
    34  	AccessGroupName  string
    35  	MountTargetCount int
    36  	FileSystemType   string
    37  }
    38  
    39  func (self *SAccessGroup) GetName() string {
    40  	return self.AccessGroupName
    41  }
    42  
    43  func (self *SAccessGroup) GetGlobalId() string {
    44  	return fmt.Sprintf("%s/%s", self.GetFileSystemType(), self.AccessGroupName)
    45  }
    46  
    47  func (self *SAccessGroup) GetFileSystemType() string {
    48  	return self.FileSystemType
    49  }
    50  
    51  func (self *SAccessGroup) IsDefault() bool {
    52  	return self.AccessGroupName == "DEFAULT_CLASSIC_GROUP_NAME" || self.AccessGroupName == "DEFAULT_VPC_GROUP_NAME"
    53  }
    54  
    55  func (self *SAccessGroup) GetDesc() string {
    56  	return self.Description
    57  }
    58  
    59  func (self *SAccessGroup) GetMountTargetCount() int {
    60  	return self.MountTargetCount
    61  }
    62  
    63  func (self *SAccessGroup) GetNetworkType() string {
    64  	return strings.ToLower(self.AccessGroupType)
    65  }
    66  
    67  func (self *SAccessGroup) GetMaxPriority() int {
    68  	return 1
    69  }
    70  
    71  func (self *SAccessGroup) GetMinPriority() int {
    72  	return 100
    73  }
    74  
    75  func (self *SAccessGroup) Delete() error {
    76  	return self.region.DeleteAccessGroup(self.FileSystemType, self.AccessGroupName)
    77  }
    78  
    79  func (self *SAccessGroup) GetSupporedUserAccessTypes() []cloudprovider.TUserAccessType {
    80  	return []cloudprovider.TUserAccessType{
    81  		cloudprovider.UserAccessTypeAllSquash,
    82  		cloudprovider.UserAccessTypeRootSquash,
    83  		cloudprovider.UserAccessTypeNoRootSquash,
    84  	}
    85  }
    86  
    87  func (self *SAccessGroup) GetRules() ([]cloudprovider.AccessGroupRule, error) {
    88  	rules := []SAccessGroupRule{}
    89  	num := 1
    90  	for {
    91  		part, total, err := self.region.GetAccessGroupRules(self.AccessGroupName, 50, num)
    92  		if err != nil {
    93  			return nil, errors.Wrapf(err, "GetAccessGroupRules")
    94  		}
    95  		rules = append(rules, part...)
    96  		if len(rules) >= total {
    97  			break
    98  		}
    99  	}
   100  	ret := []cloudprovider.AccessGroupRule{}
   101  	for i := range rules {
   102  		rule := cloudprovider.AccessGroupRule{
   103  			ExternalId: rules[i].AccessRuleId,
   104  			Priority:   rules[i].Priority,
   105  			Source:     rules[i].SourceCidrIp,
   106  		}
   107  		switch rules[i].RWAccess {
   108  		case "RDWR":
   109  			rule.RWAccessType = cloudprovider.RWAccessTypeRW
   110  		case "RDONLY":
   111  			rule.RWAccessType = cloudprovider.RWAccessTypeR
   112  		}
   113  		switch rules[i].UserAccess {
   114  		case "no_squash":
   115  			rule.UserAccessType = cloudprovider.UserAccessTypeNoRootSquash
   116  		case "root_squash":
   117  			rule.UserAccessType = cloudprovider.UserAccessTypeRootSquash
   118  		case "all_squash":
   119  			rule.UserAccessType = cloudprovider.UserAccessTypeAllSquash
   120  		}
   121  		ret = append(ret, rule)
   122  	}
   123  	return ret, nil
   124  }
   125  
   126  func (self *SRegion) getAccessGroups(fsType string, pageSize, pageNum int) ([]SAccessGroup, int, error) {
   127  	if pageSize < 1 || pageSize > 100 {
   128  		pageSize = 50
   129  	}
   130  	if pageNum < 1 {
   131  		pageNum = 1
   132  	}
   133  	params := map[string]string{
   134  		"RegionId":       self.RegionId,
   135  		"PageSize":       fmt.Sprintf("%d", pageSize),
   136  		"PageNumber":     fmt.Sprintf("%d", pageNum),
   137  		"FileSystemType": fsType,
   138  	}
   139  	resp, err := self.nasRequest("DescribeAccessGroups", params)
   140  	if err != nil {
   141  		return nil, 0, errors.Wrapf(err, "DescribeAccessGroups")
   142  	}
   143  
   144  	ret := struct {
   145  		TotalCount   int
   146  		AccessGroups struct {
   147  			AccessGroup []SAccessGroup
   148  		}
   149  	}{}
   150  	err = resp.Unmarshal(&ret)
   151  	if err != nil {
   152  		return nil, 0, errors.Wrapf(err, "resp.Unmarshal")
   153  	}
   154  	return ret.AccessGroups.AccessGroup, ret.TotalCount, nil
   155  }
   156  
   157  type SAccessGroupRule struct {
   158  	RWAccess     string
   159  	UserAccess   string
   160  	Priority     int
   161  	SourceCidrIp string
   162  	AccessRuleId string
   163  }
   164  
   165  func (self *SRegion) GetAccessGroupRules(groupName string, pageSize, pageNum int) ([]SAccessGroupRule, int, error) {
   166  	if pageSize < 1 || pageSize > 100 {
   167  		pageSize = 50
   168  	}
   169  	if pageNum < 1 {
   170  		pageNum = 1
   171  	}
   172  	params := map[string]string{
   173  		"RegionId":        self.RegionId,
   174  		"AccessGroupName": groupName,
   175  		"PageSize":        fmt.Sprintf("%d", pageSize),
   176  		"PageNumber":      fmt.Sprintf("%d", pageNum),
   177  	}
   178  	resp, err := self.nasRequest("DescribeAccessRules", params)
   179  	if err != nil {
   180  		return nil, 0, errors.Wrapf(err, "DescribeAccessRules")
   181  	}
   182  	ret := struct {
   183  		TotalCount  int
   184  		AccessRules struct {
   185  			AccessRule []SAccessGroupRule
   186  		}
   187  	}{}
   188  	err = resp.Unmarshal(&ret)
   189  	if err != nil {
   190  		return nil, 0, errors.Wrapf(err, "resp.Unmarshal")
   191  	}
   192  	return ret.AccessRules.AccessRule, ret.TotalCount, nil
   193  }
   194  
   195  func (self *SRegion) GetAccessGroups(fsType string) ([]SAccessGroup, error) {
   196  	accessGroups := []SAccessGroup{}
   197  	num := 1
   198  	for {
   199  		part, total, err := self.getAccessGroups(fsType, 50, num)
   200  		if err != nil {
   201  			if e, ok := errors.Cause(err).(*alierr.ServerError); ok && e.ErrorCode() == "Region.NotSupported" {
   202  				return accessGroups, nil
   203  			}
   204  			return nil, errors.Wrapf(err, "GetAccessGroups")
   205  		}
   206  		for i := range part {
   207  			part[i].FileSystemType = fsType
   208  			accessGroups = append(accessGroups, part[i])
   209  		}
   210  		if len(accessGroups) >= total {
   211  			break
   212  		}
   213  	}
   214  	return accessGroups, nil
   215  }
   216  
   217  func (self *SRegion) GetICloudAccessGroups() ([]cloudprovider.ICloudAccessGroup, error) {
   218  	standardAccessGroups, err := self.GetAccessGroups("standard")
   219  	if err != nil {
   220  		return nil, errors.Wrapf(err, "GetAccessGroups")
   221  	}
   222  	extremeAccessGroups, err := self.GetAccessGroups("extreme")
   223  	if err != nil {
   224  		return nil, errors.Wrapf(err, "GetAccessGroups")
   225  	}
   226  	ret := []cloudprovider.ICloudAccessGroup{}
   227  	for _, accessGroups := range [][]SAccessGroup{standardAccessGroups, extremeAccessGroups} {
   228  		for i := range accessGroups {
   229  			accessGroups[i].region = self
   230  			ret = append(ret, &accessGroups[i])
   231  		}
   232  	}
   233  	return ret, nil
   234  }
   235  
   236  func (self *SRegion) GetICloudAccessGroupById(id string) (cloudprovider.ICloudAccessGroup, error) {
   237  	groups, err := self.GetICloudAccessGroups()
   238  	if err != nil {
   239  		return nil, errors.Wrapf(err, "self.GetICloudAccessGroups")
   240  	}
   241  	for i := range groups {
   242  		if groups[i].GetGlobalId() == id {
   243  			return groups[i], nil
   244  		}
   245  	}
   246  	return nil, errors.Wrapf(err, "GetICloudAccessGroupById(%s)", id)
   247  }
   248  
   249  func (self *SRegion) CreateICloudAccessGroup(opts *cloudprovider.SAccessGroup) (cloudprovider.ICloudAccessGroup, error) {
   250  	err := self.CreateAccessGroup(opts)
   251  	if err != nil {
   252  		return nil, errors.Wrapf(err, "CreateAccessGroup")
   253  	}
   254  	return self.GetICloudAccessGroupById(fmt.Sprintf("%s/%s", opts.FileSystemType, opts.Name))
   255  }
   256  
   257  func (self *SRegion) CreateAccessGroup(opts *cloudprovider.SAccessGroup) error {
   258  	params := map[string]string{
   259  		"RegionId":        self.RegionId,
   260  		"AccessGroupName": opts.Name,
   261  		"AccessGroupType": opts.NetworkType,
   262  		"FileSystemType":  opts.FileSystemType,
   263  	}
   264  	_, err := self.nasRequest("CreateAccessGroup", params)
   265  	return errors.Wrapf(err, "CreateAccessGroup")
   266  }
   267  
   268  func (self *SRegion) DeleteAccessGroup(fsType, name string) error {
   269  	params := map[string]string{
   270  		"RegionId":        self.RegionId,
   271  		"AccessGroupName": name,
   272  		"FileSystemType":  fsType,
   273  	}
   274  	_, err := self.nasRequest("DeleteAccessGroup", params)
   275  	return errors.Wrapf(err, "DeleteAccessGroup")
   276  }
   277  
   278  func (self *SRegion) DeleteAccessGroupRule(fsType, groupName, ruleId string) error {
   279  	params := map[string]string{
   280  		"RegionId":        self.RegionId,
   281  		"AccessRuleId":    ruleId,
   282  		"AccessGroupName": groupName,
   283  		"FileSystemType":  fsType,
   284  	}
   285  	_, err := self.nasRequest("DeleteAccessRule", params)
   286  	return errors.Wrapf(err, "DeleteAccessRule")
   287  }
   288  
   289  func (self *SRegion) CreateAccessGroupRule(source, fsType, groupName string, rwType cloudprovider.TRWAccessType, userType cloudprovider.TUserAccessType, priority int) error {
   290  	params := map[string]string{
   291  		"RegionId":        self.RegionId,
   292  		"SourceCidrIp":    source,
   293  		"AccessGroupName": groupName,
   294  		"Priority":        fmt.Sprintf("%d", priority),
   295  		"FileSystemType":  fsType,
   296  	}
   297  	switch rwType {
   298  	case cloudprovider.RWAccessTypeR:
   299  		params["RWAccessType"] = "RDONLY"
   300  	case cloudprovider.RWAccessTypeRW:
   301  		params["RWAccessType"] = "RDWR"
   302  	}
   303  	switch userType {
   304  	case cloudprovider.UserAccessTypeAllSquash:
   305  		params["UserAccessType"] = "all_squash"
   306  	case cloudprovider.UserAccessTypeRootSquash:
   307  		params["UserAccessType"] = "root_squash"
   308  	case cloudprovider.UserAccessTypeNoRootSquash:
   309  		params["UserAccessType"] = "no_squash"
   310  	}
   311  	_, err := self.nasRequest("CreateAccessRule", params)
   312  	return errors.Wrapf(err, "CreateAccessRule")
   313  }
   314  
   315  func (self *SAccessGroup) SyncRules(common, added, removed cloudprovider.AccessGroupRuleSet) error {
   316  	for _, rule := range removed {
   317  		err := self.region.DeleteAccessGroupRule(self.FileSystemType, self.AccessGroupName, rule.ExternalId)
   318  		if err != nil {
   319  			return errors.Wrapf(err, "DeleteAccessGroupRule")
   320  		}
   321  	}
   322  	for _, rule := range added {
   323  		err := self.region.CreateAccessGroupRule(rule.Source, self.FileSystemType, self.AccessGroupName, rule.RWAccessType, rule.UserAccessType, rule.Priority)
   324  		if err != nil {
   325  			return errors.Wrapf(err, "CreateAccessGroupRule")
   326  		}
   327  	}
   328  	return nil
   329  }