quobyte.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // Package quobyte represents a golang API for the Quobyte Storage System
  2. package quobyte
  3. import (
  4. "net/http"
  5. "regexp"
  6. )
  7. // retry policy codes
  8. const (
  9. RetryNever string = "NEVER"
  10. RetryInteractive string = "INTERACTIVE"
  11. RetryInfinitely string = "INFINITELY"
  12. RetryOncePerTarget string = "ONCE_PER_TARGET"
  13. )
  14. var UUIDValidator = regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")
  15. type QuobyteClient struct {
  16. client *http.Client
  17. url string
  18. username string
  19. password string
  20. apiRetryPolicy string
  21. }
  22. func (client *QuobyteClient) SetAPIRetryPolicy(retry string) {
  23. client.apiRetryPolicy = retry
  24. }
  25. func (client *QuobyteClient) GetAPIRetryPolicy() string {
  26. return client.apiRetryPolicy
  27. }
  28. // NewQuobyteClient creates a new Quobyte API client
  29. func NewQuobyteClient(url string, username string, password string) *QuobyteClient {
  30. return &QuobyteClient{
  31. client: &http.Client{},
  32. url: url,
  33. username: username,
  34. password: password,
  35. apiRetryPolicy: RetryInteractive,
  36. }
  37. }
  38. // CreateVolume creates a new Quobyte volume. Its root directory will be owned by given user and group
  39. func (client QuobyteClient) CreateVolume(request *CreateVolumeRequest) (string, error) {
  40. var response volumeUUID
  41. tenantUUID, err := client.GetTenantUUID(request.TenantID)
  42. if err != nil {
  43. return "", err
  44. }
  45. request.TenantID = tenantUUID
  46. if err = client.sendRequest("createVolume", request, &response); err != nil {
  47. return "", err
  48. }
  49. return response.VolumeUUID, nil
  50. }
  51. // GetVolumeUUID resolves the volumeUUID for the given volume and tenant name.
  52. // This method should be used when it is not clear if the given string is volume UUID or Name.
  53. func (client QuobyteClient) GetVolumeUUID(volume, tenant string) (string, error) {
  54. if len(volume) != 0 && !IsValidUUID(volume) {
  55. tenantUUID, err := client.GetTenantUUID(tenant)
  56. if err != nil {
  57. return "", err
  58. }
  59. volUUID, err := client.ResolveVolumeNameToUUID(volume, tenantUUID)
  60. if err != nil {
  61. return "", err
  62. }
  63. return volUUID, nil
  64. }
  65. return volume, nil
  66. }
  67. // GetTenantUUID resolves the tenatnUUID for the given name
  68. // This method should be used when it is not clear if the given string is Tenant UUID or Name.
  69. func (client QuobyteClient) GetTenantUUID(tenant string) (string, error) {
  70. if len(tenant) != 0 && !IsValidUUID(tenant) {
  71. tenantUUID, err := client.ResolveTenantNameToUUID(tenant)
  72. if err != nil {
  73. return "", err
  74. }
  75. return tenantUUID, nil
  76. }
  77. return tenant, nil
  78. }
  79. // ResolveVolumeNameToUUID resolves a volume name to a UUID
  80. func (client *QuobyteClient) ResolveVolumeNameToUUID(volumeName, tenant string) (string, error) {
  81. request := &resolveVolumeNameRequest{
  82. VolumeName: volumeName,
  83. TenantDomain: tenant,
  84. }
  85. var response volumeUUID
  86. if err := client.sendRequest("resolveVolumeName", request, &response); err != nil {
  87. return "", err
  88. }
  89. return response.VolumeUUID, nil
  90. }
  91. // DeleteVolumeByResolvingNamesToUUID deletes the volume by resolving the volume name and tenant name to
  92. // respective UUID if required.
  93. // This method should be used if the given volume, tenant information is name or UUID.
  94. func (client *QuobyteClient) DeleteVolumeByResolvingNamesToUUID(volume, tenant string) error {
  95. volumeUUID, err := client.GetVolumeUUID(volume, tenant)
  96. if err != nil {
  97. return err
  98. }
  99. return client.DeleteVolume(volumeUUID)
  100. }
  101. // DeleteVolume deletes a Quobyte volume
  102. func (client *QuobyteClient) DeleteVolume(UUID string) error {
  103. return client.sendRequest(
  104. "deleteVolume",
  105. &volumeUUID{
  106. VolumeUUID: UUID,
  107. },
  108. nil)
  109. }
  110. // DeleteVolumeByName deletes a volume by a given name
  111. func (client *QuobyteClient) DeleteVolumeByName(volumeName, tenant string) error {
  112. uuid, err := client.ResolveVolumeNameToUUID(volumeName, tenant)
  113. if err != nil {
  114. return err
  115. }
  116. return client.DeleteVolume(uuid)
  117. }
  118. // GetClientList returns a list of all active clients
  119. func (client *QuobyteClient) GetClientList(tenant string) (GetClientListResponse, error) {
  120. request := &getClientListRequest{
  121. TenantDomain: tenant,
  122. }
  123. var response GetClientListResponse
  124. if err := client.sendRequest("getClientListRequest", request, &response); err != nil {
  125. return response, err
  126. }
  127. return response, nil
  128. }
  129. // SetVolumeQuota sets a Quota to the specified Volume
  130. func (client *QuobyteClient) SetVolumeQuota(volumeUUID string, quotaSize uint64) error {
  131. request := &setQuotaRequest{
  132. Quotas: []*quota{
  133. &quota{
  134. Consumer: []*consumingEntity{
  135. &consumingEntity{
  136. Type: "VOLUME",
  137. Identifier: volumeUUID,
  138. },
  139. },
  140. Limits: []*resource{
  141. &resource{
  142. Type: "LOGICAL_DISK_SPACE",
  143. Value: quotaSize,
  144. },
  145. },
  146. },
  147. },
  148. }
  149. return client.sendRequest("setQuota", request, nil)
  150. }
  151. // GetTenant returns the Tenant configuration for all specified tenants
  152. func (client *QuobyteClient) GetTenant(tenantIDs []string) (GetTenantResponse, error) {
  153. request := &getTenantRequest{TenantIDs: tenantIDs}
  154. var response GetTenantResponse
  155. err := client.sendRequest("getTenant", request, &response)
  156. if err != nil {
  157. return response, err
  158. }
  159. return response, nil
  160. }
  161. // GetTenantMap returns a map that contains all tenant names and there ID's
  162. func (client *QuobyteClient) GetTenantMap() (map[string]string, error) {
  163. result := map[string]string{}
  164. response, err := client.GetTenant([]string{})
  165. if err != nil {
  166. return result, err
  167. }
  168. for _, tenant := range response.Tenants {
  169. result[tenant.Name] = tenant.TenantID
  170. }
  171. return result, nil
  172. }
  173. // SetTenant creates a Tenant with the specified name
  174. func (client *QuobyteClient) SetTenant(tenantName string) (string, error) {
  175. request := &setTenantRequest{
  176. &TenantDomainConfiguration{
  177. Name: tenantName,
  178. },
  179. retryPolicy{client.GetAPIRetryPolicy()},
  180. }
  181. var response setTenantResponse
  182. err := client.sendRequest("setTenant", request, &response)
  183. if err != nil {
  184. return "", err
  185. }
  186. return response.TenantID, nil
  187. }
  188. // IsValidUUID Validates the given uuid
  189. func IsValidUUID(uuid string) bool {
  190. return UUIDValidator.MatchString(uuid)
  191. }
  192. // ResolveTenantNameToUUID Returns UUID for given name, error if not found.
  193. func (client *QuobyteClient) ResolveTenantNameToUUID(name string) (string, error) {
  194. request := &resolveTenantNameRequest{
  195. TenantName: name,
  196. }
  197. var response resolveTenantNameResponse
  198. err := client.sendRequest("resolveTenantName", request, &response)
  199. if err != nil {
  200. return "", err
  201. }
  202. return response.TenantID, nil
  203. }