golang-client/volume/v2/volume.go
Dean Troyer 753e96dd4a Fix unit tests
* OpenStack CI (Zuul?) puts repos under test in a repo named for the
  running job rather than the actual repo name, Go doesn't like ths.
  Get the actual package name from glide.yaml to build the golang
  workspace rather than the current directory.
* Only install glide on OS/X if it is not already found
* Hack out a bunch of the volume v3 stuff that I should not have merged
  before the unit job was working...the revert fails now too, so this
  is just a fine mess that I am going to clean up now.

Change-Id: I66b359fc1bfd91e686ef0b3f068e582b009e1ea5
2017-01-18 10:52:41 -06:00

211 lines
6.6 KiB
Go

// Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
/*
Package volume implements a client library for accessing OpenStack Volume service
Volumes and VolumeDetails can be retrieved using the api.
In addition more complex filtering and sort queries can by using the VolumeQueryParameters.
*/
package volume_v2
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"git.openstack.org/openstack/golang-client.git/openstack"
"git.openstack.org/openstack/golang-client.git/util"
)
// Service is a client service that can make
// requests against a OpenStack volume service.
// Below is an example on creating an volume service and getting volumes:
// volumeService := volume.VolumeService{Client: *http.DefaultClient, TokenId: tokenId, Url: "http://volumeservicelocation"}
// volumes:= volumeService.Volumes()
type Service struct {
Session openstack.Session
Client http.Client
URL string
}
// Response is a structure for all properties of
// an volume for a non detailed query
type Response struct {
ID string `json:"id"`
Links []map[string]string `json:"links"`
Name string `json:"name"`
}
// DetailResponse is a structure for all properties of
// an volume for a detailed query
type DetailResponse struct {
ID string `json:"id"`
Attachments []map[string]string `json:"attachments"`
Links []map[string]string `json:"links"`
Metadata map[string]string `json:"metadata"`
Protected bool `json:"protected"`
Status string `json:"status"`
MigrationStatus string `json:"migration_status"`
UserID string `json:"user_id"`
Encrypted bool `json:"encrypted"`
Multiattach bool `json:"multiattach"`
CreatedAt util.RFC8601DateTime `json:"created_at"`
Description string `json:"description"`
Volume_type string `json:"volume_type"`
Name string `json:"name"`
Source_volid string `json:"source_volid"`
Snapshot_id string `json:"snapshot_id"`
Size int64 `json:"size"`
Aavailability_zone string `json:"availability_zone"`
Rreplication_status string `json:"replication_status"`
Consistencygroup_id string `json:"consistencygroup_id"`
}
// QueryParameters is a structure that
// contains the filter, sort, and paging parameters for
// an volume or volumedetail query.
type QueryParameters struct {
All_tenant int64
Marker string
Limit int64
SortKey string
SortDirection SortDirection
}
// SortDirection of the sort, ascending or descending.
type SortDirection string
const (
// Desc specifies the sort direction to be descending.
Desc SortDirection = "desc"
// Asc specifies the sort direction to be ascending.
Asc SortDirection = "asc"
)
// Volumes will issue a get request to OpenStack to retrieve the list of volumes.
func (volumeService Service) Volumes() (volume []Response, err error) {
return volumeService.QueryVolumes(nil)
}
// VolumesDetail will issue a get request to OpenStack to retrieve the list of volumes complete with
// additional details.
func (volumeService Service) VolumesDetail() (volume []DetailResponse, err error) {
return volumeService.QueryVolumesDetail(nil)
}
// QueryVolumes will issue a get request with the specified VolumeQueryParameters to retrieve the list of
// volumes.
func (volumeService Service) QueryVolumes(queryParameters *QueryParameters) ([]Response, error) {
volumesContainer := volumesResponse{}
err := volumeService.queryVolumes(false /*includeDetails*/, &volumesContainer, queryParameters)
if err != nil {
return nil, err
}
return volumesContainer.Volumes, nil
}
// QueryVolumesDetail will issue a get request with the specified QueryParameters to retrieve the list of
// volumes with additional details.
func (volumeService Service) QueryVolumesDetail(queryParameters *QueryParameters) ([]DetailResponse, error) {
volumesDetailContainer := volumesDetailResponse{}
err := volumeService.queryVolumes(true /*includeDetails*/, &volumesDetailContainer, queryParameters)
if err != nil {
return nil, err
}
return volumesDetailContainer.Volumes, nil
}
func (volumeService Service) queryVolumes(includeDetails bool, volumesResponseContainer interface{}, queryParameters *QueryParameters) error {
urlPostFix := "/volumes"
if includeDetails {
urlPostFix = urlPostFix + "/detail"
}
reqURL, err := buildQueryURL(volumeService, queryParameters, urlPostFix)
if err != nil {
return err
}
var headers http.Header = http.Header{}
headers.Set("Accept", "application/json")
resp, err := volumeService.Session.Get(reqURL.String(), nil, &headers)
if err != nil {
return err
}
err = util.CheckHTTPResponseStatusCode(resp)
if err != nil {
return err
}
rbody, err := ioutil.ReadAll(resp.Body)
if err != nil {
return errors.New("aaa")
}
if err = json.Unmarshal(rbody, &volumesResponseContainer); err != nil {
return err
}
return nil
}
func buildQueryURL(volumeService Service, queryParameters *QueryParameters, volumePartialURL string) (*url.URL, error) {
reqURL, err := url.Parse(volumeService.URL)
if err != nil {
return nil, err
}
if queryParameters != nil {
values := url.Values{}
if queryParameters.All_tenant != 0 {
values.Set("all_tenant", fmt.Sprintf("%d", queryParameters.All_tenant))
}
if queryParameters.Limit != 0 {
values.Set("limit", fmt.Sprintf("%d", queryParameters.Limit))
}
if queryParameters.Marker != "" {
values.Set("marker", queryParameters.Marker)
}
if queryParameters.SortKey != "" {
values.Set("sort_key", queryParameters.SortKey)
}
if queryParameters.SortDirection != "" {
values.Set("sort_dir", string(queryParameters.SortDirection))
}
if len(values) > 0 {
reqURL.RawQuery = values.Encode()
}
}
reqURL.Path += volumePartialURL
return reqURL, nil
}
type volumesDetailResponse struct {
Volumes []DetailResponse `json:"volumes"`
}
type volumesResponse struct {
Volumes []Response `json:"volumes"`
}