volume.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package storageos
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "net/http"
  6. "net/url"
  7. "github.com/storageos/go-api/types"
  8. )
  9. var (
  10. // VolumeAPIPrefix is a partial path to the HTTP endpoint.
  11. VolumeAPIPrefix = "volumes"
  12. // ErrNoSuchVolume is the error returned when the volume does not exist.
  13. ErrNoSuchVolume = errors.New("no such volume")
  14. // ErrVolumeInUse is the error returned when the volume requested to be removed is still in use.
  15. ErrVolumeInUse = errors.New("volume in use and cannot be removed")
  16. )
  17. // VolumeList returns the list of available volumes.
  18. func (c *Client) VolumeList(opts types.ListOptions) ([]*types.Volume, error) {
  19. listOpts := doOptions{
  20. fieldSelector: opts.FieldSelector,
  21. labelSelector: opts.LabelSelector,
  22. namespace: opts.Namespace,
  23. context: opts.Context,
  24. }
  25. if opts.LabelSelector != "" {
  26. query := url.Values{}
  27. query.Add("labelSelector", opts.LabelSelector)
  28. listOpts.values = query
  29. }
  30. resp, err := c.do("GET", VolumeAPIPrefix, listOpts)
  31. if err != nil {
  32. return nil, err
  33. }
  34. defer resp.Body.Close()
  35. var volumes []*types.Volume
  36. if err := json.NewDecoder(resp.Body).Decode(&volumes); err != nil {
  37. return nil, err
  38. }
  39. return volumes, nil
  40. }
  41. // Volume returns a volume by its reference.
  42. func (c *Client) Volume(namespace string, ref string) (*types.Volume, error) {
  43. path, err := namespacedRefPath(namespace, VolumeAPIPrefix, ref)
  44. if err != nil {
  45. return nil, err
  46. }
  47. resp, err := c.do("GET", path, doOptions{})
  48. if err != nil {
  49. if e, ok := err.(*Error); ok && e.Status == http.StatusNotFound {
  50. return nil, ErrNoSuchVolume
  51. }
  52. return nil, err
  53. }
  54. defer resp.Body.Close()
  55. var volume types.Volume
  56. if err := json.NewDecoder(resp.Body).Decode(&volume); err != nil {
  57. return nil, err
  58. }
  59. return &volume, nil
  60. }
  61. // VolumeCreate creates a volume on the server and returns the new object.
  62. func (c *Client) VolumeCreate(opts types.VolumeCreateOptions) (*types.Volume, error) {
  63. path, err := namespacedPath(opts.Namespace, VolumeAPIPrefix)
  64. if err != nil {
  65. return nil, err
  66. }
  67. resp, err := c.do("POST", path, doOptions{
  68. data: opts,
  69. context: opts.Context,
  70. })
  71. if err != nil {
  72. return nil, err
  73. }
  74. defer resp.Body.Close()
  75. var volume types.Volume
  76. if err := json.NewDecoder(resp.Body).Decode(&volume); err != nil {
  77. return nil, err
  78. }
  79. return &volume, nil
  80. }
  81. // VolumeUpdate updates a volume on the server.
  82. func (c *Client) VolumeUpdate(opts types.VolumeUpdateOptions) (*types.Volume, error) {
  83. ref := opts.Name
  84. if IsUUID(opts.ID) {
  85. ref = opts.ID
  86. }
  87. path, err := namespacedRefPath(opts.Namespace, VolumeAPIPrefix, ref)
  88. if err != nil {
  89. return nil, err
  90. }
  91. resp, err := c.do("PUT", path, doOptions{
  92. data: opts,
  93. context: opts.Context,
  94. })
  95. if err != nil {
  96. return nil, err
  97. }
  98. defer resp.Body.Close()
  99. var volume types.Volume
  100. if err := json.NewDecoder(resp.Body).Decode(&volume); err != nil {
  101. return nil, err
  102. }
  103. return &volume, nil
  104. }
  105. // VolumeDelete removes a volume by its reference.
  106. func (c *Client) VolumeDelete(opts types.DeleteOptions) error {
  107. deleteOpts := doOptions{
  108. namespace: opts.Namespace,
  109. force: opts.Force,
  110. context: opts.Context,
  111. }
  112. resp, err := c.do("DELETE", VolumeAPIPrefix+"/"+opts.Name, deleteOpts)
  113. if err != nil {
  114. if e, ok := err.(*Error); ok {
  115. if e.Status == http.StatusNotFound {
  116. return ErrNoSuchVolume
  117. }
  118. if e.Status == http.StatusConflict {
  119. return ErrVolumeInUse
  120. }
  121. }
  122. return err
  123. }
  124. defer resp.Body.Close()
  125. return nil
  126. }
  127. // VolumeMount updates the volume with the client that mounted it.
  128. func (c *Client) VolumeMount(opts types.VolumeMountOptions) error {
  129. ref := opts.Name
  130. if IsUUID(opts.ID) {
  131. ref = opts.ID
  132. }
  133. path, err := namespacedRefPath(opts.Namespace, VolumeAPIPrefix, ref)
  134. if err != nil {
  135. return err
  136. }
  137. resp, err := c.do("POST", path+"/mount", doOptions{
  138. data: opts,
  139. context: opts.Context,
  140. })
  141. if err != nil {
  142. if e, ok := err.(*Error); ok {
  143. if e.Status == http.StatusNotFound {
  144. return ErrNoSuchVolume
  145. }
  146. if e.Status == http.StatusConflict {
  147. return ErrVolumeInUse
  148. }
  149. }
  150. return err
  151. }
  152. defer resp.Body.Close()
  153. return nil
  154. }
  155. // VolumeUnmount removes the client from the mount reference.
  156. func (c *Client) VolumeUnmount(opts types.VolumeUnmountOptions) error {
  157. ref := opts.Name
  158. if IsUUID(opts.ID) {
  159. ref = opts.ID
  160. }
  161. path, err := namespacedRefPath(opts.Namespace, VolumeAPIPrefix, ref)
  162. if err != nil {
  163. return err
  164. }
  165. resp, err := c.do("POST", path+"/unmount", doOptions{
  166. data: opts,
  167. context: opts.Context,
  168. })
  169. if err != nil {
  170. if e, ok := err.(*Error); ok {
  171. if e.Status == http.StatusNotFound {
  172. return ErrNoSuchVolume
  173. }
  174. if e.Status == http.StatusConflict {
  175. return ErrVolumeInUse
  176. }
  177. }
  178. return err
  179. }
  180. defer resp.Body.Close()
  181. return nil
  182. }