
* 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
211 lines
6.6 KiB
Go
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"`
|
|
}
|