Skip to content

Commit 2abd357

Browse files
authored
add support for openstack api metrics (kubernetes#2077)
1 parent debd751 commit 2abd357

File tree

7 files changed

+60
-26
lines changed

7 files changed

+60
-26
lines changed

cmd/cinder-csi-plugin/main.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@ import (
3232
)
3333

3434
var (
35-
endpoint string
36-
nodeID string
37-
cloudconfig []string
38-
cluster string
35+
endpoint string
36+
nodeID string
37+
cloudconfig []string
38+
cluster string
39+
httpEndpoint string
3940
)
4041

4142
func main() {
@@ -88,7 +89,7 @@ func main() {
8889
}
8990

9091
cmd.PersistentFlags().StringVar(&cluster, "cluster", "", "The identifier of the cluster that the plugin is running in.")
91-
92+
cmd.PersistentFlags().StringVar(&httpEndpoint, "http-endpoint", "", "The TCP network address where the HTTP server for diagnostics, including metrics and leader election health check, will listen (example: `:8080`). The default is empty string, which means the server is disabled.")
9293
openstack.AddExtraFlags(pflag.CommandLine)
9394

9495
code := cli.Run(cmd)
@@ -99,7 +100,7 @@ func handle() {
99100

100101
// Initialize cloud
101102
d := cinder.NewDriver(endpoint, cluster)
102-
openstack.InitOpenStackProvider(cloudconfig)
103+
openstack.InitOpenStackProvider(cloudconfig, httpEndpoint)
103104
cloud, err := openstack.GetOpenStackProvider()
104105
if err != nil {
105106
klog.Warningf("Failed to GetOpenStackProvider: %v", err)

pkg/csi/cinder/openstack/openstack.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package openstack
1818

1919
import (
2020
"fmt"
21+
"net/http"
2122
"os"
2223

2324
"github.com/gophercloud/gophercloud"
@@ -28,7 +29,9 @@ import (
2829
"github.com/spf13/pflag"
2930
gcfg "gopkg.in/gcfg.v1"
3031
"k8s.io/cloud-provider-openstack/pkg/client"
32+
"k8s.io/cloud-provider-openstack/pkg/metrics"
3133
"k8s.io/cloud-provider-openstack/pkg/util/metadata"
34+
"k8s.io/component-base/metrics/legacyregistry"
3235
"k8s.io/klog/v2"
3336
)
3437

@@ -131,7 +134,20 @@ const defaultMaxVolAttachLimit int64 = 256
131134
var OsInstance IOpenStack
132135
var configFiles = []string{"/etc/cloud.conf"}
133136

134-
func InitOpenStackProvider(cfgFiles []string) {
137+
func InitOpenStackProvider(cfgFiles []string, httpEndpoint string) {
138+
metrics.RegisterMetrics("cinder-csi")
139+
if httpEndpoint != "" {
140+
mux := http.NewServeMux()
141+
mux.Handle("/metrics", legacyregistry.HandlerWithReset())
142+
go func() {
143+
err := http.ListenAndServe(httpEndpoint, mux)
144+
if err != nil {
145+
klog.Fatalf("failed to listen & serve metrics from %q: %v", httpEndpoint, err)
146+
}
147+
klog.Infof("metrics available in %q", httpEndpoint)
148+
}()
149+
}
150+
135151
configFiles = cfgFiles
136152
klog.V(2).Infof("InitOpenStackProvider configFiles: %s", configFiles)
137153
}

pkg/csi/cinder/openstack/openstack_instances.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ package openstack
22

33
import (
44
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
5+
"k8s.io/cloud-provider-openstack/pkg/metrics"
56
)
67

78
// GetInstanceByID returns server with specified instanceID
89
func (os *OpenStack) GetInstanceByID(instanceID string) (*servers.Server, error) {
10+
mc := metrics.NewMetricContext("server", "get")
911
server, err := servers.Get(os.compute, instanceID).Extract()
10-
if err != nil {
12+
if mc.ObserveRequest(err) != nil {
1113
return nil, err
1214
}
1315
return server, nil

pkg/csi/cinder/openstack/openstack_snapshots.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/gophercloud/gophercloud/openstack/blockstorage/v3/snapshots"
2828
"github.com/gophercloud/gophercloud/pagination"
2929
"k8s.io/apimachinery/pkg/util/wait"
30+
"k8s.io/cloud-provider-openstack/pkg/metrics"
3031
"k8s.io/klog/v2"
3132
)
3233

@@ -67,9 +68,9 @@ func (os *OpenStack) CreateSnapshot(name, volID string, tags *map[string]string)
6768
opts.Metadata = *tags
6869
}
6970
// TODO: Do some check before really call openstack API on the input
70-
71+
mc := metrics.NewMetricContext("snapshot", "create")
7172
snap, err := snapshots.Create(os.blockstorage, opts).Extract()
72-
if err != nil {
73+
if mc.ObserveRequest(err) != nil {
7374
return &snapshots.Snapshot{}, err
7475
}
7576
// There's little value in rewrapping these gophercloud types into yet another abstraction/type, instead just
@@ -103,6 +104,7 @@ func (os *OpenStack) ListSnapshots(filters map[string]string) ([]snapshots.Snaps
103104
klog.V(3).Infof("Not a valid filter key %s", key)
104105
}
105106
}
107+
mc := metrics.NewMetricContext("snapshot", "list")
106108
err := snapshots.List(os.blockstorage, opts).EachPage(func(page pagination.Page) (bool, error) {
107109
var err error
108110

@@ -126,7 +128,7 @@ func (os *OpenStack) ListSnapshots(filters map[string]string) ([]snapshots.Snaps
126128

127129
return false, nil
128130
})
129-
if err != nil {
131+
if mc.ObserveRequest(err) != nil {
130132
return nil, nextPageToken, err
131133
}
132134

@@ -135,17 +137,19 @@ func (os *OpenStack) ListSnapshots(filters map[string]string) ([]snapshots.Snaps
135137

136138
// DeleteSnapshot issues a request to delete the Snapshot with the specified ID from the Cinder backend
137139
func (os *OpenStack) DeleteSnapshot(snapID string) error {
140+
mc := metrics.NewMetricContext("snapshot", "delete")
138141
err := snapshots.Delete(os.blockstorage, snapID).ExtractErr()
139-
if err != nil {
142+
if mc.ObserveRequest(err) != nil {
140143
klog.Errorf("Failed to delete snapshot: %v", err)
141144
}
142145
return err
143146
}
144147

145148
// GetSnapshotByID returns snapshot details by id
146149
func (os *OpenStack) GetSnapshotByID(snapshotID string) (*snapshots.Snapshot, error) {
150+
mc := metrics.NewMetricContext("snapshot", "get")
147151
s, err := snapshots.Get(os.blockstorage, snapshotID).Extract()
148-
if err != nil {
152+
if mc.ObserveRequest(err) != nil {
149153
klog.Errorf("Failed to get snapshot: %v", err)
150154
return nil, err
151155
}

pkg/csi/cinder/openstack/openstack_volumes.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
2828
"github.com/gophercloud/gophercloud/pagination"
2929
"k8s.io/apimachinery/pkg/util/wait"
30+
"k8s.io/cloud-provider-openstack/pkg/metrics"
3031
cpoerrors "k8s.io/cloud-provider-openstack/pkg/util/errors"
3132

3233
"k8s.io/klog/v2"
@@ -65,8 +66,9 @@ func (os *OpenStack) CreateVolume(name string, size int, vtype, availability str
6566
opts.Metadata = *tags
6667
}
6768

69+
mc := metrics.NewMetricContext("volume", "create")
6870
vol, err := volumes.Create(os.blockstorage, opts).Extract()
69-
if err != nil {
71+
if mc.ObserveRequest(err) != nil {
7072
return nil, err
7173
}
7274

@@ -79,6 +81,7 @@ func (os *OpenStack) ListVolumes(limit int, startingToken string) ([]volumes.Vol
7981
var vols []volumes.Volume
8082

8183
opts := volumes.ListOpts{Limit: limit, Marker: startingToken}
84+
mc := metrics.NewMetricContext("volume", "list")
8285
err := volumes.List(os.blockstorage, opts).EachPage(func(page pagination.Page) (bool, error) {
8386
var err error
8487

@@ -102,7 +105,7 @@ func (os *OpenStack) ListVolumes(limit int, startingToken string) ([]volumes.Vol
102105

103106
return false, nil
104107
})
105-
if err != nil {
108+
if mc.ObserveRequest(err) != nil {
106109
return nil, nextPageToken, err
107110
}
108111

@@ -125,8 +128,9 @@ func (os *OpenStack) GetVolumesByName(n string) ([]volumes.Volume, error) {
125128
}
126129

127130
opts := volumes.ListOpts{Name: n}
131+
mc := metrics.NewMetricContext("volume", "list")
128132
pages, err := volumes.List(blockstorageClient, opts).AllPages()
129-
if err != nil {
133+
if mc.ObserveRequest(err) != nil {
130134
return nil, err
131135
}
132136

@@ -148,15 +152,16 @@ func (os *OpenStack) DeleteVolume(volumeID string) error {
148152
return fmt.Errorf("Cannot delete the volume %q, it's still attached to a node", volumeID)
149153
}
150154

155+
mc := metrics.NewMetricContext("volume", "delete")
151156
err = volumes.Delete(os.blockstorage, volumeID, nil).ExtractErr()
152-
return err
157+
return mc.ObserveRequest(err)
153158
}
154159

155160
// GetVolume retrieves Volume by its ID.
156161
func (os *OpenStack) GetVolume(volumeID string) (*volumes.Volume, error) {
157-
162+
mc := metrics.NewMetricContext("volume", "get")
158163
vol, err := volumes.Get(os.blockstorage, volumeID).Extract()
159-
if err != nil {
164+
if mc.ObserveRequest(err) != nil {
160165
return nil, err
161166
}
162167

@@ -189,11 +194,12 @@ func (os *OpenStack) AttachVolume(instanceID, volumeID string) (string, error) {
189194
computeServiceClient.Microversion = "2.60"
190195
}
191196

197+
mc := metrics.NewMetricContext("volume", "attach")
192198
_, err = volumeattach.Create(computeServiceClient, instanceID, &volumeattach.CreateOpts{
193199
VolumeID: volume.ID,
194200
}).Extract()
195201

196-
if err != nil {
202+
if mc.ObserveRequest(err) != nil {
197203
return "", fmt.Errorf("failed to attach %s volume to %s compute: %v", volumeID, instanceID, err)
198204
}
199205

@@ -276,8 +282,9 @@ func (os *OpenStack) DetachVolume(instanceID, volumeID string) error {
276282
// Incase volume is of type multiattach, it could be attached to more than one instance
277283
for _, att := range volume.Attachments {
278284
if att.ServerID == instanceID {
285+
mc := metrics.NewMetricContext("volume", "detach")
279286
err = volumeattach.Delete(os.compute, instanceID, volume.ID).ExtractErr()
280-
if err != nil {
287+
if mc.ObserveRequest(err) != nil {
281288
return fmt.Errorf("failed to detach volume %s from compute %s : %v", volume.ID, instanceID, err)
282289
}
283290
klog.V(2).Infof("Successfully detached volume: %s from compute: %s", volume.ID, instanceID)
@@ -357,9 +364,11 @@ func (os *OpenStack) ExpandVolume(volumeID string, status string, newSize int) e
357364
// https://docs.openstack.org/cinder/latest/contributor/api_microversion_history.html#id40
358365
blockstorageClient.Microversion = "3.42"
359366

360-
return volumeexpand.ExtendSize(blockstorageClient, volumeID, extendOpts).ExtractErr()
367+
mc := metrics.NewMetricContext("volume", "expand")
368+
return mc.ObserveRequest(volumeexpand.ExtendSize(blockstorageClient, volumeID, extendOpts).ExtractErr())
361369
case VolumeAvailableStatus:
362-
return volumeexpand.ExtendSize(os.blockstorage, volumeID, extendOpts).ExtractErr()
370+
mc := metrics.NewMetricContext("volume", "expand")
371+
return mc.ObserveRequest(volumeexpand.ExtendSize(os.blockstorage, volumeID, extendOpts).ExtractErr())
363372
}
364373

365374
// cinder volume can not be expanded when volume status is not volumeInUseStatus or not volumeAvailableStatus

pkg/metrics/metrics.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ func (mc *MetricContext) Observe(om *OpenstackMetrics, err error) error {
5959
return err
6060
}
6161

62-
func RegisterMetrics() {
62+
func RegisterMetrics(component string) {
6363
doRegisterAPIMetrics()
64-
doRegisterOccmMetrics()
64+
if component == "occm" {
65+
doRegisterOccmMetrics()
66+
}
6567
}

pkg/openstack/openstack.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ type Config struct {
160160
}
161161

162162
func init() {
163-
metrics.RegisterMetrics()
163+
metrics.RegisterMetrics("occm")
164164

165165
cloudprovider.RegisterCloudProvider(ProviderName, func(config io.Reader) (cloudprovider.Interface, error) {
166166
cfg, err := ReadConfig(config)

0 commit comments

Comments
 (0)