Skip to content
This repository has been archived by the owner on Aug 1, 2023. It is now read-only.

Commit

Permalink
Merge pull request #448 from DSpeichert/telemetry
Browse files Browse the repository at this point in the history
[RFR] OpenStack Telemetry v2
  • Loading branch information
jrperritt authored Jul 13, 2016
2 parents b8b50b9 + 3849090 commit 1f02c2b
Show file tree
Hide file tree
Showing 8 changed files with 640 additions and 3 deletions.
16 changes: 13 additions & 3 deletions openstack/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,20 @@ func NewClient(endpoint string) (*gophercloud.ProviderClient, error) {
}

parts := strings.Split(path[0:len(path)-1], "/")
for index,version := range(parts) {
for index, version := range parts {
if 2 <= len(version) && len(version) <= 4 && strings.HasPrefix(version, "v") {
_, err := strconv.ParseFloat(version[1:], 64)
if err == nil {
// post version suffixes in path are not supported
// version must be on the last index
if index < len(parts) - 1 {
if index < len(parts)-1 {
return nil, fmt.Errorf("Path suffixes (after version) are not supported.")
}
switch version {
case "v2.0", "v3":
// valid version found, strip from base
return &gophercloud.ProviderClient{
IdentityBase: base[0:len(base)-len(version)-1],
IdentityBase: base[0 : len(base)-len(version)-1],
IdentityEndpoint: endpoint,
}, nil
default:
Expand Down Expand Up @@ -356,3 +356,13 @@ func NewImageServiceV2(client *gophercloud.ProviderClient, eo gophercloud.Endpoi
Endpoint: url,
ResourceBase: url + "v2/"}, nil
}

// NewTelemetryV2 creates a ServiceClient that may be used to access the v2 telemetry service.
func NewTelemetryV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) {
eo.ApplyDefaults("metering")
url, err := client.EndpointLocator(eo)
if err != nil {
return nil, err
}
return &gophercloud.ServiceClient{ProviderClient: client, Endpoint: url}, nil
}
1 change: 1 addition & 0 deletions openstack/telemetry/v2/meters/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package meters
207 changes: 207 additions & 0 deletions openstack/telemetry/v2/meters/fixtures.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
// +build fixtures

package meters

import (
"fmt"
"net/http"
"testing"
"time"

th "github.com/rackspace/gophercloud/testhelper"
"github.com/rackspace/gophercloud/testhelper/client"
)

// MeterListBody contains the canned body of a meters.List response.
const MeterListBody = `
[
{
"meter_id": "YmQ5NDMxYzEtOGQ2OS00YWQzLTgwM2EtOGQ0YTZiODlmZDM2K2luc3RhbmNl",
"name": "instance",
"project_id": "35b17138-b364-4e6a-a131-8f3099c5be68",
"resource_id": "bd9431c1-8d69-4ad3-803a-8d4a6b89fd36",
"source": "openstack",
"type": "gauge",
"unit": "instance",
"user_id": "efd87807-12d2-4b38-9c70-5f5c2ac427ff"
},
{
"user_id": "7ya0f7a33717400b951037d55b929c53",
"name": "cpu_util",
"resource_id": "5b88239b-8ba1-44ff-a154-978cbda23479",
"source": "region2",
"meter_id": "NWI4ODIzOWAtOGJhMS00NGZhLWExNTQtOTc4Y2JkYTIzNDc5K2NwdV91dGls",
"project_id": "69e6e7c4ed8b434e92feacbf3d4891fd",
"type": "gauge",
"unit": "%%"
}
]
`

// MeterShowBody is the canned body of a Get request on an existing meter.
const MeterShowBody = `
[
{
"counter_name": "instance",
"counter_type": "gauge",
"counter_unit": "instance",
"counter_volume": 1.0,
"message_id": "5460acce-4fd6-480d-ab18-9735ec7b1996",
"project_id": "35b17138-b364-4e6a-a131-8f3099c5be68",
"resource_id": "bd9431c1-8d69-4ad3-803a-8d4a6b89fd36",
"resource_metadata": {
"name1": "value1",
"name2": "value2"
},
"source": "openstack",
"timestamp": "2013-11-21T12:33:08.323533",
"user_id": "efd87807-12d2-4b38-9c70-5f5c2ac427ff"
}
]
`

// MeterStatisticsBody is the canned body of a Get statistics request on an existing meter.
const MeterStatisticsBody = `
[
{
"avg": 4.5,
"count": 10,
"duration": 300.0,
"duration_end": "2013-01-04T16:47:00",
"duration_start": "2013-01-04T16:42:00",
"max": 9.0,
"min": 1.0,
"period": 7200,
"period_end": "2013-01-04T18:00:00",
"period_start": "2013-01-04T16:00:00",
"sum": 45.0,
"unit": "GiB"
},
{
"count": 28162,
"duration_start": "2015-06-27T20:52:08",
"min": 0.06999999999999999,
"max": 10.06799336650083,
"duration_end": "2015-07-27T20:47:02",
"period": 0,
"sum": 44655.782463977856,
"period_end": "2015-07-17T16:43:31",
"duration": 2591694.0,
"period_start": "2015-07-17T16:43:31",
"avg": 1.5856751105737468,
"groupby": null,
"unit": "%%"
}
]
`

var (
// MeterHerp is a Meter struct that should correspond to the first result in *[]Meter.
MeterHerp = Meter{
MeterId: "YmQ5NDMxYzEtOGQ2OS00YWQzLTgwM2EtOGQ0YTZiODlmZDM2K2luc3RhbmNl",
Name: "instance",
ProjectId: "35b17138-b364-4e6a-a131-8f3099c5be68",
ResourceId: "bd9431c1-8d69-4ad3-803a-8d4a6b89fd36",
Source: "openstack",
Type: "gauge",
Unit: "instance",
UserId: "efd87807-12d2-4b38-9c70-5f5c2ac427ff",
}

// MeterDerp is a Meter struct that should correspond to the second result in *[]Meter.
MeterDerp = Meter{
MeterId: "NWI4ODIzOWAtOGJhMS00NGZhLWExNTQtOTc4Y2JkYTIzNDc5K2NwdV91dGls",
Name: "cpu_util",
ProjectId: "69e6e7c4ed8b434e92feacbf3d4891fd",
ResourceId: "5b88239b-8ba1-44ff-a154-978cbda23479",
Source: "region2",
Type: "gauge",
Unit: "%",
UserId: "7ya0f7a33717400b951037d55b929c53",
}

ShowHerp = OldSample{
Name: "instance",
Type: "gauge",
Unit: "instance",
Volume: 1.0,
MessageId: "5460acce-4fd6-480d-ab18-9735ec7b1996",
ProjectId: "35b17138-b364-4e6a-a131-8f3099c5be68",
ResourceId: "bd9431c1-8d69-4ad3-803a-8d4a6b89fd36",
ResourceMetadata: map[string]string{
"name1": "value1",
"name2": "value2",
},
Source: "openstack",
Timestamp: time.Date(2013, time.November, 21, 12, 33, 8, 323533000, time.UTC),
UserId: "efd87807-12d2-4b38-9c70-5f5c2ac427ff",
}

// StatisticsHerp is a Statistics struct that should correspond to the first result in *[]Statistics.
StatisticsHerp = Statistics{
Avg: 4.5,
Count: 10,
Duration: 300.0,
DurationEnd: "2013-01-04T16:47:00",
DurationStart: "2013-01-04T16:42:00",
Max: 9.0,
Min: 1.0,
Period: 7200,
PeriodEnd: "2013-01-04T18:00:00",
PeriodStart: "2013-01-04T16:00:00",
Sum: 45.0,
Unit: "GiB",
}

// StatisticsDerp is a Statistics struct that should correspond to the second result in *[]Statistics.
StatisticsDerp = Statistics{
Avg: 1.5856751105737468,
Count: 28162,
Duration: 2591694.0,
DurationEnd: "2015-07-27T20:47:02",
DurationStart: "2015-06-27T20:52:08",
Max: 10.06799336650083,
Min: 0.06999999999999999,
Period: 0,
PeriodEnd: "2015-07-17T16:43:31",
PeriodStart: "2015-07-17T16:43:31",
Sum: 44655.782463977856,
Unit: "%",
}
)

// HandleMeterListSuccessfully sets up the test server to respond to a meters List request.
func HandleMeterListSuccessfully(t *testing.T) {
th.Mux.HandleFunc("/v2/meters", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "GET")
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)

w.Header().Add("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, MeterListBody)
})
}

// HandleMeterShowSuccessfully sets up the test server to respond to a show meter request.
func HandleMeterShowSuccessfully(t *testing.T) {
th.Mux.HandleFunc("/v2/meters/instance", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "GET")
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)

w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, MeterShowBody)
})
}

// HandleMeterStatisticsSuccessfully sets up the test server to respond to a show meter request.
func HandleMeterStatisticsSuccessfully(t *testing.T) {
th.Mux.HandleFunc("/v2/meters/memory/statistics", func(w http.ResponseWriter, r *http.Request) {
th.TestMethod(t, r, "GET")
th.TestHeader(t, r, "X-Auth-Token", client.TokenID)

w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, MeterStatisticsBody)
})
}
149 changes: 149 additions & 0 deletions openstack/telemetry/v2/meters/requests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package meters

import (
"github.com/rackspace/gophercloud"
)

// ListOptsBuilder allows extensions to add additional parameters to the
// List request.
type ListOptsBuilder interface {
ToMeterListQuery() (string, error)
}

// ListOpts allows the filtering and sorting of collections through
// the API. Filtering is achieved by passing in struct field values that map to
// the server attributes you want to see returned.
type ListOpts struct {
QueryField string `q:"q.field"`
QueryOp string `q:"q.op"`
QueryValue string `q:"q.value"`

// ID of the last-seen item from the previous response
Marker string `q:"marker"`

// Optional, maximum number of results to return
Limit int `q:"limit"`
}

// ToMeterListQuery formats a ListOpts into a query string.
func (opts ListOpts) ToMeterListQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
}
return q.String(), nil
}

// List makes a request against the API to list meters accessible to you.
func List(client *gophercloud.ServiceClient, opts ListOptsBuilder) ListResult {
var res ListResult
url := listURL(client)

if opts != nil {
query, err := opts.ToMeterListQuery()
if err != nil {
res.Err = err
return res
}
url += query
}

_, res.Err = client.Get(url, &res.Body, &gophercloud.RequestOpts{})
return res
}

// ShowOptsBuilder allows extensions to add additional parameters to the
// Show request.
type ShowOptsBuilder interface {
ToShowQuery() (string, error)
}

// ShowOpts allows the filtering and sorting of collections through
// the API. Filtering is achieved by passing in struct field values that map to
// the server attributes you want to see returned.
type ShowOpts struct {
QueryField string `q:"q.field"`
QueryOp string `q:"q.op"`
QueryValue string `q:"q.value"`

// ID of the last-seen item from the previous response
Marker string `q:"marker"`

// Optional, maximum number of results to return
Limit int `q:"limit"`
}

// ToMeterShowQuery formats a ShowOpts into a query string.
func (opts ShowOpts) ToShowQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
}
return q.String(), nil
}

// Show makes a request against the API to show a specific meter
func Show(client *gophercloud.ServiceClient, meterName string, opts ShowOptsBuilder) ShowResult {
var res ShowResult
url := showURL(client, meterName)

if opts != nil {
query, err := opts.ToShowQuery()
if err != nil {
res.Err = err
return res
}
url += query
}

_, res.Err = client.Get(url, &res.Body, &gophercloud.RequestOpts{})
return res
}

// StatisticsOptsBuilder allows extensions to add additional parameters to the
// List request.
type MeterStatisticsOptsBuilder interface {
ToMeterStatisticsQuery() (string, error)
}

// StatisticsOpts allows the filtering and sorting of collections through
// the API. Filtering is achieved by passing in struct field values that map to
// the server attributes you want to see returned.
type MeterStatisticsOpts struct {
QueryField string `q:"q.field"`
QueryOp string `q:"q.op"`
QueryValue string `q:"q.value"`

// Optional group by
GroupBy string `q:"groupby"`

// Optional number of seconds in a period
Period int `q:"period"`
}

// ToStatisticsQuery formats a StatisticsOpts into a query string.
func (opts MeterStatisticsOpts) ToMeterStatisticsQuery() (string, error) {
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return "", err
}
return q.String(), nil
}

// List makes a request against the API to list meters accessible to you.
func MeterStatistics(client *gophercloud.ServiceClient, n string, opts MeterStatisticsOptsBuilder) StatisticsResult {
var res StatisticsResult
url := statisticsURL(client, n)

if opts != nil {
query, err := opts.ToMeterStatisticsQuery()
if err != nil {
res.Err = err
return res
}
url += query
}

_, res.Err = client.Get(url, &res.Body, &gophercloud.RequestOpts{})
return res
}
Loading

0 comments on commit 1f02c2b

Please sign in to comment.