filesystem.go 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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. package aliyun
  15. import (
  16. "fmt"
  17. "strings"
  18. "time"
  19. "yunion.io/x/jsonutils"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/pkg/utils"
  22. billing_api "yunion.io/x/cloudmux/pkg/apis/billing"
  23. api "yunion.io/x/cloudmux/pkg/apis/compute"
  24. "yunion.io/x/cloudmux/pkg/cloudprovider"
  25. "yunion.io/x/cloudmux/pkg/multicloud"
  26. )
  27. type SupportedFeatures struct {
  28. SupportedFeature []string
  29. }
  30. type MountTargets struct {
  31. MountTarget []SMountTarget
  32. }
  33. type Package struct {
  34. }
  35. type Packages struct {
  36. Package []Package
  37. }
  38. type SFileSystem struct {
  39. multicloud.SNasBase
  40. AliyunTags
  41. region *SRegion
  42. Status string
  43. Description string
  44. StorageType string
  45. MountTargetCountLimit int
  46. Ldap string
  47. ZoneId string
  48. // 2021-03-22T10:08:15CST
  49. CreateTime string
  50. MeteredIASize int
  51. SupportedFeatures SupportedFeatures
  52. MountTargets MountTargets
  53. AutoSnapshotPolicyId string
  54. MeteredSize int64
  55. EncryptType int
  56. Capacity int64
  57. ProtocolType string
  58. ChargeType string
  59. Packages Packages
  60. ExpiredTime string
  61. FileSystemType string
  62. FileSystemId string
  63. RegionId string
  64. ResourceGroupId string
  65. }
  66. func (self *SFileSystem) GetId() string {
  67. return self.FileSystemId
  68. }
  69. func (self *SFileSystem) GetGlobalId() string {
  70. return self.FileSystemId
  71. }
  72. func (self *SFileSystem) GetName() string {
  73. if len(self.Description) > 0 {
  74. return self.Description
  75. }
  76. return self.FileSystemId
  77. }
  78. func (self *SFileSystem) GetFileSystemType() string {
  79. return self.FileSystemType
  80. }
  81. func (self *SFileSystem) GetMountTargetCountLimit() int {
  82. return self.MountTargetCountLimit
  83. }
  84. func (self *SFileSystem) GetStatus() string {
  85. switch self.Status {
  86. case "", "Running":
  87. return api.NAS_STATUS_AVAILABLE
  88. case "Extending":
  89. return api.NAS_STATUS_EXTENDING
  90. case "Stopping", "Stopped":
  91. return api.NAS_STATUS_UNAVAILABLE
  92. case "Pending":
  93. return api.NAS_STATUS_CREATING
  94. default:
  95. return api.NAS_STATUS_UNKNOWN
  96. }
  97. }
  98. func (self *SFileSystem) GetBillintType() string {
  99. if self.ChargeType == "PayAsYouGo" {
  100. return billing_api.BILLING_TYPE_POSTPAID
  101. }
  102. return billing_api.BILLING_TYPE_PREPAID
  103. }
  104. func (self *SFileSystem) GetStorageType() string {
  105. return strings.ToLower(self.StorageType)
  106. }
  107. func (self *SFileSystem) GetProtocol() string {
  108. return self.ProtocolType
  109. }
  110. func (self *SFileSystem) GetCapacityGb() int64 {
  111. return self.Capacity
  112. }
  113. func (self *SFileSystem) GetUsedCapacityGb() int64 {
  114. return self.MeteredSize
  115. }
  116. func (self *SFileSystem) GetZoneId() string {
  117. return self.ZoneId
  118. }
  119. func (self *SFileSystem) Delete() error {
  120. return self.region.DeleteFileSystem(self.FileSystemId)
  121. }
  122. func (self *SFileSystem) GetCreatedAt() time.Time {
  123. ret, _ := time.Parse("2006-01-02T15:04:05CST", self.CreateTime)
  124. if !ret.IsZero() {
  125. ret = ret.Add(time.Hour * 8)
  126. }
  127. return ret
  128. }
  129. func (self *SFileSystem) GetExpiredAt() time.Time {
  130. ret, _ := time.Parse("2006-01-02T15:04:05CST", self.ExpiredTime)
  131. if !ret.IsZero() {
  132. ret = ret.Add(time.Hour * 8)
  133. }
  134. return ret
  135. }
  136. func (self *SFileSystem) Refresh() error {
  137. fs, err := self.region.GetFileSystem(self.FileSystemId)
  138. if err != nil {
  139. return errors.Wrapf(err, "GetFileSystem(%s)", self.FileSystemId)
  140. }
  141. return jsonutils.Update(self, fs)
  142. }
  143. func (self *SRegion) GetFileSystems(id string, pageSize, pageNum int) ([]SFileSystem, int, error) {
  144. if pageSize < 1 || pageSize > 100 {
  145. pageSize = 50
  146. }
  147. if pageNum < 1 {
  148. pageNum = 1
  149. }
  150. params := map[string]string{
  151. "RegionId": self.RegionId,
  152. "PageSize": fmt.Sprintf("%d", pageSize),
  153. "PageNumber": fmt.Sprintf("%d", pageNum),
  154. }
  155. if len(id) > 0 {
  156. params["FileSystemId"] = id
  157. }
  158. resp, err := self.nasRequest("DescribeFileSystems", params)
  159. if err != nil {
  160. return nil, 0, errors.Wrapf(err, "DescribeFileSystems")
  161. }
  162. ret := struct {
  163. TotalCount int
  164. FileSystems struct {
  165. FileSystem []SFileSystem
  166. }
  167. }{}
  168. err = resp.Unmarshal(&ret)
  169. if err != nil {
  170. return nil, 0, errors.Wrapf(err, "resp.Unmarshal")
  171. }
  172. return ret.FileSystems.FileSystem, ret.TotalCount, nil
  173. }
  174. func (self *SRegion) GetICloudFileSystems() ([]cloudprovider.ICloudFileSystem, error) {
  175. nas := []SFileSystem{}
  176. num := 1
  177. for {
  178. part, total, err := self.GetFileSystems("", 100, num)
  179. if err != nil {
  180. return nil, errors.Wrapf(err, "GetFileSystems")
  181. }
  182. nas = append(nas, part...)
  183. if total <= len(nas) {
  184. break
  185. }
  186. num++
  187. }
  188. ret := []cloudprovider.ICloudFileSystem{}
  189. for i := range nas {
  190. nas[i].region = self
  191. ret = append(ret, &nas[i])
  192. }
  193. return ret, nil
  194. }
  195. func (self *SRegion) GetFileSystem(id string) (*SFileSystem, error) {
  196. if len(id) == 0 {
  197. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty id")
  198. }
  199. nas, total, err := self.GetFileSystems(id, 1, 1)
  200. if err != nil {
  201. return nil, errors.Wrapf(err, "GetFileSystems")
  202. }
  203. if total == 1 {
  204. nas[0].region = self
  205. return &nas[0], nil
  206. }
  207. if total == 0 {
  208. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", id)
  209. }
  210. return nil, errors.Wrapf(cloudprovider.ErrDuplicateId, "%s", id)
  211. }
  212. func (self *SRegion) GetICloudFileSystemById(id string) (cloudprovider.ICloudFileSystem, error) {
  213. fs, err := self.GetFileSystem(id)
  214. if err != nil {
  215. return nil, errors.Wrapf(err, "self.GetFileSystem")
  216. }
  217. return fs, nil
  218. }
  219. func (self *SRegion) CreateMountTarget(opts *cloudprovider.SMountTargetCreateOptions) (*SMountTarget, error) {
  220. params := map[string]string{
  221. "RegionId": self.RegionId,
  222. "FileSystemId": opts.FileSystemId,
  223. "AccessGroupName": strings.TrimPrefix(strings.TrimPrefix(opts.AccessGroupId, "extreme/"), "standard/"),
  224. "NetworkType": utils.Capitalize(opts.NetworkType),
  225. "VpcId": opts.VpcId,
  226. "VSwitchId": opts.NetworkId,
  227. }
  228. resp, err := self.nasRequest("CreateMountTarget", params)
  229. if err != nil {
  230. return nil, errors.Wrapf(err, "CreateMountTarget")
  231. }
  232. ret := struct {
  233. MountTargetDomain string
  234. }{}
  235. err = resp.Unmarshal(&ret)
  236. if err != nil {
  237. return nil, errors.Wrapf(err, "resp.Unmarshal")
  238. }
  239. mts, _, err := self.GetMountTargets(opts.FileSystemId, ret.MountTargetDomain, 10, 1)
  240. if err != nil {
  241. return nil, errors.Wrapf(err, "self.GetMountTargets")
  242. }
  243. for i := range mts {
  244. if mts[i].MountTargetDomain == ret.MountTargetDomain {
  245. return &mts[i], nil
  246. }
  247. }
  248. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "afeter create with mount domain %s", ret.MountTargetDomain)
  249. }
  250. func (self *SFileSystem) CreateMountTarget(opts *cloudprovider.SMountTargetCreateOptions) (cloudprovider.ICloudMountTarget, error) {
  251. mt, err := self.region.CreateMountTarget(opts)
  252. if err != nil {
  253. return nil, errors.Wrapf(err, "CreateMountTarget")
  254. }
  255. mt.fs = self
  256. return mt, nil
  257. }
  258. func (self *SRegion) DeleteFileSystem(id string) error {
  259. params := map[string]string{
  260. "RegionId": self.RegionId,
  261. "FileSystemId": id,
  262. }
  263. _, err := self.nasRequest("DeleteFileSystem", params)
  264. return errors.Wrapf(err, "DeleteFileSystem")
  265. }
  266. func (self *SRegion) CreateICloudFileSystem(opts *cloudprovider.FileSystemCraeteOptions) (cloudprovider.ICloudFileSystem, error) {
  267. fs, err := self.CreateFileSystem(opts)
  268. if err != nil {
  269. return nil, errors.Wrapf(err, "self.CreateFileSystem")
  270. }
  271. return fs, nil
  272. }
  273. func (self *SRegion) CreateFileSystem(opts *cloudprovider.FileSystemCraeteOptions) (*SFileSystem, error) {
  274. params := map[string]string{
  275. "RegionId": self.RegionId,
  276. "ProtocolType": opts.Protocol,
  277. "ZoneId": opts.ZoneId,
  278. "EncryptType": "0",
  279. "FileSystemType": opts.FileSystemType,
  280. "StorageType": opts.StorageType,
  281. "ClientToken": utils.GenRequestId(20),
  282. "Description": opts.Name,
  283. }
  284. if self.GetCloudEnv() == ALIYUN_FINANCE_CLOUDENV {
  285. if opts.FileSystemType == "standard" {
  286. opts.ZoneId = strings.Replace(opts.ZoneId, "cn-shanghai-finance-1", "jr-cn-shanghai-", 1)
  287. opts.ZoneId = strings.Replace(opts.ZoneId, "cn-shenzhen-finance-1", "jr-cn-shenzhen-", 1)
  288. params["ZoneId"] = opts.ZoneId
  289. }
  290. }
  291. switch opts.FileSystemType {
  292. case "standard":
  293. params["StorageType"] = utils.Capitalize(opts.StorageType)
  294. case "cpfs":
  295. params["ProtocolType"] = "cpfs"
  296. switch opts.StorageType {
  297. case "advance_100":
  298. params["Bandwidth"] = "100"
  299. case "advance_200":
  300. params["Bandwidth"] = "200"
  301. }
  302. case "extreme":
  303. params["Capacity"] = fmt.Sprintf("%d", opts.Capacity)
  304. }
  305. if len(opts.VpcId) > 0 {
  306. params["VpcId"] = opts.VpcId
  307. }
  308. if len(opts.NetworkId) > 0 {
  309. params["VSwitchId"] = opts.NetworkId
  310. }
  311. if opts.BillingCycle != nil {
  312. params["ChargeType"] = "Subscription"
  313. params["Duration"] = fmt.Sprintf("%d", opts.BillingCycle.GetMonths())
  314. }
  315. resp, err := self.nasRequest("CreateFileSystem", params)
  316. if err != nil {
  317. return nil, errors.Wrapf(err, "CreateFileSystem")
  318. }
  319. fsId, _ := resp.GetString("FileSystemId")
  320. return self.GetFileSystem(fsId)
  321. }
  322. func (self *SFileSystem) SetTags(tags map[string]string, replace bool) error {
  323. return self.region.SetResourceTags(ALIYUN_SERVICE_NAS, "filesystem", self.FileSystemId, tags, replace)
  324. }
  325. func (self *SFileSystem) GetProjectId() string {
  326. return self.ResourceGroupId
  327. }