From 3820417bb2bf19aede40a24b259de29980619dfe Mon Sep 17 00:00:00 2001 From: wnxn Date: Wed, 13 Jun 2018 15:59:14 +0800 Subject: [PATCH 1/4] add storageclass metrics list api --- pkg/apis/v1alpha/storage/storage_handler.go | 20 ++++- pkg/models/storage.go | 99 ++++++++++++++++++--- 2 files changed, 104 insertions(+), 15 deletions(-) diff --git a/pkg/apis/v1alpha/storage/storage_handler.go b/pkg/apis/v1alpha/storage/storage_handler.go index 1964cf31b..e18866f5f 100644 --- a/pkg/apis/v1alpha/storage/storage_handler.go +++ b/pkg/apis/v1alpha/storage/storage_handler.go @@ -19,6 +19,11 @@ func Register(ws *restful.WebService, subPath string) { To(GetScMetrics).Filter(route.RouteLogging)). Consumes(restful.MIME_JSON, restful.MIME_XML). Produces(restful.MIME_JSON) + + ws.Route(ws.GET(subPath+"/storageclasses/metrics"). + To(GetScMetricsList).Filter(route.RouteLogging)). + Consumes(restful.MIME_JSON, restful.MIME_XML). + Produces(restful.MIME_JSON) } // List all PersistentVolumeClaims of a specific StorageClass @@ -34,14 +39,23 @@ func GetPvcListBySc(request *restful.Request, response *restful.Response) { response.WriteAsJson(result) } -// Get metrics of a specific StorageClass +// Get StorageClass item // Extended API URL: "GET /api/v1alpha1/storage/storageclasses/{name}/metrics" func GetScMetrics(request *restful.Request, response *restful.Response) { scName := request.PathParameter("storageclass") - metrics, err := models.GetScMetrics(scName) + result, err := models.GetScItemMetrics(scName) + if err != nil { + response.WriteError(http.StatusInternalServerError, err) + } + response.WriteAsJson(result) +} + +// Get StorageClass item list +// Extended API URI: "GET /api/v1alpha1/storage/storageclasses/metrics" +func GetScMetricsList(request *restful.Request, response *restful.Response) { + result, err := models.GetScItemMetricsList() if err != nil { response.WriteError(http.StatusInternalServerError, err) } - result := models.ScMetrics{Name: scName, Metrics: metrics} response.WriteAsJson(result) } diff --git a/pkg/models/storage.go b/pkg/models/storage.go index 4980d1629..b9dfa85d3 100644 --- a/pkg/models/storage.go +++ b/pkg/models/storage.go @@ -5,7 +5,10 @@ import ( "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/golang/glog" + v13 "k8s.io/api/storage/v1" "kubesphere.io/kubesphere/pkg/client" + "strconv" ) type PvcListBySc struct { @@ -14,13 +17,20 @@ type PvcListBySc struct { } type ScMetrics struct { - Name string `json:"name"` - Metrics StorageMetrics `json:"metrics"` + Capacity string `json:"capacity,omitempty"` + Usage string `json:"usage,omitempty"` + PvcNumber string `json:"pvcNumber"` } -type StorageMetrics struct { - Capacity string `json:"capacity,omitempty"` - Usage string `json:"usage,omitempty"` +// StorageClass metrics item +type ScMetricsItem struct { + Name string `json:"name"` + Metrics ScMetrics `json:"metrics"` +} + +// StorageClass metrics items list +type ScMetricsItemList struct { + Items []ScMetricsItem `json:"items"` } // List persistent volume claims of a specific storage class @@ -45,23 +55,88 @@ func GetPvcListBySc(storageclass string) (res []v12.PersistentVolumeClaim, err e return res, nil } -// Get metrics of a specific storage class -func GetScMetrics(storageclass string) (res StorageMetrics, err error) { +// Get info of metrics +func GetScEntityMetrics(scname string) (ScMetrics, error) { // Create Kubernetes client cli := client.NewK8sClient() - // Get persistent volumes + + // Get PV pvList, err := cli.CoreV1().PersistentVolumes().List(v1.ListOptions{}) if err != nil { - return StorageMetrics{}, err + glog.Error(err) + } + // Get PVC + pvcList, err := GetPvcListBySc(scname) + if err != nil { + return ScMetrics{}, err } + // Get storage usage + // Gathering usage of a specific StorageClass var total resource.Quantity - // Gathering metrics of a specific storage class for _, volume := range pvList.Items { - if volume.Spec.StorageClassName != storageclass { + if volume.Spec.StorageClassName != scname { continue } total.Add(volume.Spec.Capacity[v12.ResourceStorage]) } - return StorageMetrics{Usage: total.String()}, nil + usage := total.String() + + // Get PVC number + pvcNum := len(pvcList) + + return ScMetrics{Usage: usage, PvcNumber: strconv.Itoa(pvcNum)}, nil +} + +// Get raw information of a SC +func GetScEntity(scname string) (res v13.StorageClass, err error) { + // Create Kubernetes client + cli := client.NewK8sClient() + // Get SC + sc, err := cli.StorageV1().StorageClasses().Get(scname, v1.GetOptions{}) + if err != nil { + return v13.StorageClass{}, err + } + return *sc, nil +} + +// Get SC item +func GetScItemMetrics(scname string) (res ScMetricsItem, err error) { + // Check SC exist + _, err = GetScEntity(scname) + if err != nil { + return ScMetricsItem{}, err + } + + metrics, err := GetScEntityMetrics(scname) + if err != nil { + return ScMetricsItem{}, err + } + + result := ScMetricsItem{scname, metrics} + return result, nil +} + +// Get SC item list +func GetScItemMetricsList() (res ScMetricsItemList, err error) { + // Create Kubernetes client + cli := client.NewK8sClient() + // Get StorageClass list + scList, err := cli.StorageV1().StorageClasses().List(v1.ListOptions{}) + if err != nil { + return ScMetricsItemList{}, err + } + if scList == nil { + return ScMetricsItemList{}, nil + } + // Set return value + res = ScMetricsItemList{} + for _, v := range scList.Items { + metrics, err := GetScEntityMetrics(v.GetName()) + if err != nil { + return ScMetricsItemList{}, err + } + res.Items = append(res.Items, ScMetricsItem{v.GetName(), metrics}) + } + return res, nil } From 48bb3d4f89e07c3cbd3cc69d08d0bd660d4da7fe Mon Sep 17 00:00:00 2001 From: wnxn Date: Wed, 13 Jun 2018 16:12:55 +0800 Subject: [PATCH 2/4] add error log --- pkg/models/storage.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkg/models/storage.go b/pkg/models/storage.go index b9dfa85d3..721c2a591 100644 --- a/pkg/models/storage.go +++ b/pkg/models/storage.go @@ -40,6 +40,7 @@ func GetPvcListBySc(storageclass string) (res []v12.PersistentVolumeClaim, err e // Get all persistent volume claims claimList, err := cli.CoreV1().PersistentVolumeClaims("").List(v1.ListOptions{}) if err != nil { + glog.Errorf("list persistent volumes error: name: \"%s\", error msg: \"%s\"", storageclass, err.Error()) return nil, err } // Select persistent volume claims which @@ -63,7 +64,8 @@ func GetScEntityMetrics(scname string) (ScMetrics, error) { // Get PV pvList, err := cli.CoreV1().PersistentVolumes().List(v1.ListOptions{}) if err != nil { - glog.Error(err) + glog.Errorf("list persistent volume request error: error msg: \"%s\"", err.Error()) + return ScMetrics{}, err } // Get PVC pvcList, err := GetPvcListBySc(scname) @@ -95,6 +97,7 @@ func GetScEntity(scname string) (res v13.StorageClass, err error) { // Get SC sc, err := cli.StorageV1().StorageClasses().Get(scname, v1.GetOptions{}) if err != nil { + glog.Errorf("get storage class request error: name: \"%s\", error msg: \"%s\"", scname, err.Error()) return v13.StorageClass{}, err } return *sc, nil @@ -124,6 +127,7 @@ func GetScItemMetricsList() (res ScMetricsItemList, err error) { // Get StorageClass list scList, err := cli.StorageV1().StorageClasses().List(v1.ListOptions{}) if err != nil { + glog.Errorf("list storage classes request error: error msg: \"%s\"", err.Error()) return ScMetricsItemList{}, err } if scList == nil { @@ -132,11 +136,11 @@ func GetScItemMetricsList() (res ScMetricsItemList, err error) { // Set return value res = ScMetricsItemList{} for _, v := range scList.Items { - metrics, err := GetScEntityMetrics(v.GetName()) + item, err := GetScItemMetrics(v.GetName()) if err != nil { return ScMetricsItemList{}, err } - res.Items = append(res.Items, ScMetricsItem{v.GetName(), metrics}) + res.Items = append(res.Items, item) } return res, nil } From 9610f70c505d32ef476d2cccb0a961b6b25101ec Mon Sep 17 00:00:00 2001 From: wnxn Date: Wed, 13 Jun 2018 16:43:08 +0800 Subject: [PATCH 3/4] make fmt --- pkg/models/storage.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/models/storage.go b/pkg/models/storage.go index 721c2a591..c61e4cd25 100644 --- a/pkg/models/storage.go +++ b/pkg/models/storage.go @@ -1,14 +1,15 @@ package models import ( + "strconv" + + "github.com/golang/glog" v12 "k8s.io/api/core/v1" + v13 "k8s.io/api/storage/v1" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/golang/glog" - v13 "k8s.io/api/storage/v1" "kubesphere.io/kubesphere/pkg/client" - "strconv" ) type PvcListBySc struct { From fc811db90ddfa4f1e0b795360cb2aed7292cf33d Mon Sep 17 00:00:00 2001 From: wnxn Date: Wed, 13 Jun 2018 17:03:36 +0800 Subject: [PATCH 4/4] modify annotation --- pkg/apis/v1alpha/storage/storage_handler.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/apis/v1alpha/storage/storage_handler.go b/pkg/apis/v1alpha/storage/storage_handler.go index e18866f5f..bd8805512 100644 --- a/pkg/apis/v1alpha/storage/storage_handler.go +++ b/pkg/apis/v1alpha/storage/storage_handler.go @@ -27,7 +27,7 @@ func Register(ws *restful.WebService, subPath string) { } // List all PersistentVolumeClaims of a specific StorageClass -// Extended API URL: "GET /api/v1alpha1/storage/storageclasses/{name}/persistentvolumeclaims" +// Extended API URL: "GET /api/v1alpha1/storage/storageclasses/{storageclass}/persistentvolumeclaims" func GetPvcListBySc(request *restful.Request, response *restful.Response) { scName := request.PathParameter("storageclass") claims, err := models.GetPvcListBySc(scName) @@ -40,7 +40,7 @@ func GetPvcListBySc(request *restful.Request, response *restful.Response) { } // Get StorageClass item -// Extended API URL: "GET /api/v1alpha1/storage/storageclasses/{name}/metrics" +// Extended API URL: "GET /api/v1alpha1/storage/storageclasses/{storageclass}/metrics" func GetScMetrics(request *restful.Request, response *restful.Response) { scName := request.PathParameter("storageclass") result, err := models.GetScItemMetrics(scName) @@ -51,7 +51,7 @@ func GetScMetrics(request *restful.Request, response *restful.Response) { } // Get StorageClass item list -// Extended API URI: "GET /api/v1alpha1/storage/storageclasses/metrics" +// Extended API URL: "GET /api/v1alpha1/storage/storageclasses/metrics" func GetScMetricsList(request *restful.Request, response *restful.Response) { result, err := models.GetScItemMetricsList() if err != nil {