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 }