Skip to content

Commit

Permalink
Add lvmlocalpv vg listing & zfspool listing (#53)
Browse files Browse the repository at this point in the history
* Make zfslocalpv client testable

Signed-off-by: Harsh Vardhan <[email protected]>
  • Loading branch information
Harsh Vardhan authored Jul 15, 2021
1 parent 7c26ad5 commit 340fefc
Show file tree
Hide file tree
Showing 12 changed files with 327 additions and 80 deletions.
6 changes: 5 additions & 1 deletion cmd/describe/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
package describe

import (
"strings"

"github.com/openebs/openebsctl/pkg/storage"
"github.com/openebs/openebsctl/pkg/util"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -50,7 +52,9 @@ func NewCmdDescribeStorage() *cobra.Command {
Example: `kubectl openebs describe storage storage-1`,
Run: func(cmd *cobra.Command, args []string) {
openebsNs, _ := cmd.Flags().GetString("openebs-namespace")
util.CheckErr(storage.Describe(args, openebsNs), util.Fatal)
casType, _ := cmd.Flags().GetString("cas-type")
casType = strings.ToLower(casType)
util.CheckErr(storage.Describe(args, openebsNs, casType), util.Fatal)
},
}
return cmd
Expand Down
1 change: 0 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,6 @@ github.com/openebs/api/v2 v2.3.0/go.mod h1:nLCaNvVjgjkjeD2a+n1fMbv5HjoEYP4XB8OAb
github.com/openebs/jiva-operator v1.12.2-0.20210607114402-811a3af7c34a h1:HuCp3D9TOhJogGTcH5JePJuebceQhPRgB5SizB0bmTg=
github.com/openebs/jiva-operator v1.12.2-0.20210607114402-811a3af7c34a/go.mod h1:5oMQaMQKa0swN1hJnAP7CEMI/MOLVz0S2Mcu0H/l0oc=
github.com/openebs/lib-csi v0.3.0/go.mod h1:uruyzJiTwRoytQPQXOf4spaezn1cjkiAXjvFGw6aY/8=
github.com/openebs/lib-csi v0.6.0 h1:nucurCo91lKNhtjbYNPJIrbJU0F4oinphZtkGWI/DEY=
github.com/openebs/lib-csi v0.6.0/go.mod h1:KWANWF2zNB8RYyELegid8PxHFrP/cdttR320NA9gVUQ=
github.com/openebs/lvm-localpv v0.6.0 h1:2LWSF/qy6jGKNAALtIN1O5y6tEKhwTGcVUcxy0Qgnpk=
github.com/openebs/lvm-localpv v0.6.0/go.mod h1:DVDU+pjCFdb3rZd4MwVVEZ2eXqq+LT16CpQTm1j0MYo=
Expand Down
61 changes: 5 additions & 56 deletions pkg/client/k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,12 @@ import (
"github.com/openebs/api/v2/pkg/apis/openebs.io/v1alpha1"
lvmclient "github.com/openebs/lvm-localpv/pkg/generated/clientset/internalclientset"
"github.com/openebs/openebsctl/pkg/util"
zfsclient "github.com/openebs/zfs-localpv/pkg/generated/clientset/internalclientset"
"github.com/pkg/errors"

cstorv1 "github.com/openebs/api/v2/pkg/apis/cstor/v1"
openebsclientset "github.com/openebs/api/v2/pkg/client/clientset/versioned"
jiva "github.com/openebs/jiva-operator/pkg/apis/openebs/v1alpha1"
zfs "github.com/openebs/zfs-localpv/pkg/apis/openebs.io/zfs/v1"
zfsBuilder "github.com/openebs/zfs-localpv/pkg/builder/volbuilder"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -65,6 +64,8 @@ type K8sClient struct {
OpenebsCS openebsclientset.Interface
// LVMCS is the client for accessing OpenEBS LVM components
LVMCS lvmclient.Interface
// ZFCS is the client for accessing OpenEBS ZFS components
ZFCS zfsclient.Interface
}

/*
Expand All @@ -88,11 +89,13 @@ func NewK8sClient(ns string) (*K8sClient, error) {
return nil, errors.Wrap(err, "failed to build OpenEBS clientset")
}
lv, _ := getLVMclient(config)
zf, _ := getZFSclient(config)
return &K8sClient{
Ns: ns,
K8sCS: k8sCS,
OpenebsCS: openebsCS,
LVMCS: lv,
ZFCS: zf,
}, nil
}

Expand Down Expand Up @@ -641,60 +644,6 @@ func (k K8sClient) GetJVTargetPod(volumeName string) (*corev1.PodList, error) {
return pods, nil
}

// GetZFSVols returns a list or a map of ZFSVolume depending upon rType & options
func (k K8sClient) GetZFSVols(volNames []string, rType util.ReturnType, labelSelector string, options util.MapOptions) (*zfs.ZFSVolumeList, map[string]zfs.ZFSVolume, error) {
config := os.Getenv("KUBECONFIG")
zvols, err := zfsBuilder.NewKubeclient(zfsBuilder.WithKubeConfigPath(config)).
WithNamespace("").
List(metav1.ListOptions{
LabelSelector: labelSelector,
})
if err != nil {
return nil, nil, err
}
var list []zfs.ZFSVolume
if len(volNames) == 0 {
list = zvols.Items
} else {
zvsMap := make(map[string]zfs.ZFSVolume)
for _, zv := range zvols.Items {
zvsMap[zv.Name] = zv
}
for _, name := range volNames {
if zv, ok := zvsMap[name]; ok {
list = append(list, zv)
} else {
fmt.Printf("Error from server (NotFound): zfsVolume %s not found\n", name)
}
}
}
if rType == util.List {
return &zfs.ZFSVolumeList{
Items: list,
}, nil, nil
}
if rType == util.Map {
zvMap := make(map[string]zfs.ZFSVolume)
switch options.Key {
case util.Label:
for _, zv := range list {
if vol, ok := zv.Labels[options.LabelKey]; ok {
zvMap[vol] = zv
}
}
return nil, zvMap, nil
case util.Name:
for _, zv := range list {
zvMap[zv.Name] = zv
}
return nil, zvMap, nil
default:
return nil, nil, errors.New("invalid map options")
}
}
return nil, nil, errors.New("invalid return type")
}

// GetCSIControllerSTS returns the CSI controller sts with a specific
// openebs-component-name label key
func (k K8sClient) GetCSIControllerSTS(name string) (*appsv1.StatefulSet, error) {
Expand Down
5 changes: 5 additions & 0 deletions pkg/client/lvmlocalpv.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,8 @@ func (k K8sClient) GetLVMvol(lVols []string, rType util.ReturnType, labelSelecto
}
return nil, nil, errors.New("invalid return type")
}

// GetLVMNodes return a list of LVMNodes
func (k K8sClient) GetLVMNodes() (*lvm.LVMNodeList, error) {
return k.LVMCS.LocalV1alpha1().LVMNodes("").List(context.TODO(), v1.ListOptions{})
}
96 changes: 96 additions & 0 deletions pkg/client/zfslocalpv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
Copyright 2020-2021 The OpenEBS Authors
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 client

import (
"context"
"fmt"

"github.com/openebs/openebsctl/pkg/util"
zfs "github.com/openebs/zfs-localpv/pkg/apis/openebs.io/zfs/v1"
zvolclient "github.com/openebs/zfs-localpv/pkg/generated/clientset/internalclientset"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/clientcmd"
)

// getLVMClient returns OpenEBS clientset by taking kubeconfig as an
// argument
func getZFSclient(kubeconfig string) (*zvolclient.Clientset, error) {
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
return nil, fmt.Errorf("could not build config from flags: %v", err)
}
client, err := zvolclient.NewForConfig(config)
if err != nil {
return nil, fmt.Errorf("could not get new config: %v", err)
}
return client, nil
}

// GetZFSVols returns a list or a map of ZFSVolume depending upon rType & options
func (k K8sClient) GetZFSVols(volNames []string, rType util.ReturnType, labelSelector string, options util.MapOptions) (*zfs.ZFSVolumeList, map[string]zfs.ZFSVolume, error) {
zvols, err := k.ZFCS.ZfsV1().ZFSVolumes("").List(context.TODO(), metav1.ListOptions{LabelSelector: labelSelector})
if err != nil {
return nil, nil, err
}
var list []zfs.ZFSVolume
if len(volNames) == 0 {
list = zvols.Items
} else {
zvsMap := make(map[string]zfs.ZFSVolume)
for _, zv := range zvols.Items {
zvsMap[zv.Name] = zv
}
for _, name := range volNames {
if zv, ok := zvsMap[name]; ok {
list = append(list, zv)
} else {
fmt.Printf("Error from server (NotFound): zfsVolume %s not found\n", name)
}
}
}
if rType == util.List {
return &zfs.ZFSVolumeList{
Items: list,
}, nil, nil
}
if rType == util.Map {
zvMap := make(map[string]zfs.ZFSVolume)
switch options.Key {
case util.Label:
for _, zv := range list {
if vol, ok := zv.Labels[options.LabelKey]; ok {
zvMap[vol] = zv
}
}
return nil, zvMap, nil
case util.Name:
for _, zv := range list {
zvMap[zv.Name] = zv
}
return nil, zvMap, nil
default:
return nil, nil, fmt.Errorf("invalid map options")
}
}
return nil, nil, fmt.Errorf("invalid return type")
}

// GetZFSNodes return a list of ZFSNodes
func (k K8sClient) GetZFSNodes() (*zfs.ZFSNodeList, error) {
return k.ZFCS.ZfsV1().ZFSNodes("").List(context.TODO(), metav1.ListOptions{})
}
5 changes: 2 additions & 3 deletions pkg/storage/cstor.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,9 @@ func GetCstorPools(c *client.K8sClient, pools []string) error {
util.Duration(time.Since(item.ObjectMeta.CreationTimestamp.Time))}})
}
if len(cpools.Items) == 0 {
fmt.Println("No Pools are found")
} else {
util.TablePrinter(util.CstorPoolListColumnDefinations, rows, printers.PrintOptions{Wide: true})
return fmt.Errorf("no cstor pools are found")
}
util.TablePrinter(util.CstorPoolListColumnDefinations, rows, printers.PrintOptions{Wide: true})
return nil
}

Expand Down
60 changes: 60 additions & 0 deletions pkg/storage/lvmlocalpv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
Copyright 2020-2021 The OpenEBS Authors
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 storage

import (
"fmt"

"github.com/openebs/openebsctl/pkg/client"
"github.com/openebs/openebsctl/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/printers"
)

const (
firstElemPrefix = `├─`
lastElemPrefix = `└─`
)

// GetVolumeGroups lists all volume groups by node
func GetVolumeGroups(c *client.K8sClient, vgs []string) error {
lvmNodes, err := c.GetLVMNodes()
if err != nil {
return err
}
var rows []metav1.TableRow
for _, lv := range lvmNodes.Items {
rows = append(rows, metav1.TableRow{Cells: []interface{}{lv.Name, "", "", ""}})
for i, vg := range lv.VolumeGroups {
var prefix string
if i < len(lv.VolumeGroups)-1 {
prefix = firstElemPrefix
} else {
prefix = lastElemPrefix
}
rows = append(rows, metav1.TableRow{Cells: []interface{}{prefix + vg.Name,
util.ConvertToIBytes(vg.Free.String()), util.ConvertToIBytes(vg.Size.String())}})
}
rows = append(rows, metav1.TableRow{Cells: []interface{}{"", "", ""}})
}
// 3. Actually print the table or return an error
if len(rows) == 0 {
return fmt.Errorf("no lvm volumegroups found")
}
util.TablePrinter(util.LVMvolgroupListColumnDefinitions, rows, printers.PrintOptions{Wide: true})
return nil
}
57 changes: 57 additions & 0 deletions pkg/storage/lvmlocalpv_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Copyright 2020-2021 The OpenEBS Authors
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 storage

import (
"testing"

fakelvmclient "github.com/openebs/lvm-localpv/pkg/generated/clientset/internalclientset/fake"
"github.com/openebs/openebsctl/pkg/client"
)

func TestGetVolumeGroup(t *testing.T) {
type args struct {
c *client.K8sClient
vg []string
}
tests := []struct {
name string
args args
wantErr bool
}{
{
"no LVM volumegroups present",
args{
c: &client.K8sClient{
Ns: "lvmlocalpv",
K8sCS: nil,
OpenebsCS: nil,
LVMCS: fakelvmclient.NewSimpleClientset(),
},
vg: nil,
},
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := GetVolumeGroups(tt.args.c, tt.args.vg); (err != nil) != tt.wantErr {
t.Errorf("GetVolumeGroups() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
Loading

0 comments on commit 340fefc

Please sign in to comment.