Skip to content

Commit

Permalink
Add support to visualize bdc
Browse files Browse the repository at this point in the history
Signed-off-by: Akash Srivastava <akashsrivastava4927@gmail.com>
  • Loading branch information
qiell committed Aug 6, 2019
1 parent 82b3c91 commit f0fa228
Show file tree
Hide file tree
Showing 14 changed files with 179 additions and 2 deletions.
33 changes: 33 additions & 0 deletions probe/kubernetes/blockdeviceclaim.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package kubernetes

import (
mayav1alpha1 "github.com/openebs/maya/pkg/apis/openebs.io/v1alpha1"
"github.com/weaveworks/scope/report"
)

// BlockDeviceClaim represent NDM BlockDeviceClaim interface
type BlockDeviceClaim interface {
Meta
GetNode(probeID string) report.Node
}

type blockDeviceClaim struct {
*mayav1alpha1.BlockDeviceClaim
Meta
}

// NewBlockDeviceClaim returns new block device claim type
func NewBlockDeviceClaim(b *mayav1alpha1.BlockDeviceClaim) BlockDeviceClaim {
return &blockDeviceClaim{BlockDeviceClaim: b, Meta: meta{b.ObjectMeta}}
}

// GetNode returns Block Device Claim as Node
func (b *blockDeviceClaim) GetNode(probeID string) report.Node {
return b.MetaNode(report.MakeBlockDeviceClaimNodeID(b.UID())).WithLatests(map[string]string{
NodeType: "Block Device Claim",
BlockDeviceName: b.Spec.BlockDeviceName,
HostName: b.Spec.HostName,
Status: string(b.Status.Phase),
report.ControlProbeID: probeID,
}).WithLatestActiveControls(Describe)
}
15 changes: 15 additions & 0 deletions probe/kubernetes/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ type Client interface {
WalkCStorVolumeReplicas(f func(CStorVolumeReplica) error) error
WalkCStorPools(f func(CStorPool) error) error
WalkBlockDevices(f func(BlockDevice) error) error
WalkBlockDeviceClaims(f func(BlockDeviceClaim) error) error
WatchPods(f func(Event, Pod))

CloneVolumeSnapshot(namespaceID, volumeSnapshotID, persistentVolumeClaimID, capacity string) error
Expand Down Expand Up @@ -118,6 +119,7 @@ type client struct {
cStorvolumeReplicaStore cache.Store
cStorPoolStore cache.Store
blockDeviceStore cache.Store
blockDeviceClaimStore cache.Store

podWatchesMutex sync.Mutex
podWatches []func(Event, Pod)
Expand Down Expand Up @@ -225,6 +227,7 @@ func NewClient(config ClientConfig) (Client, error) {
result.cStorvolumeReplicaStore = result.setupStore("cstorvolumereplicas")
result.cStorPoolStore = result.setupStore("cstorpools")
result.blockDeviceStore = result.setupStore("blockdevices")
result.blockDeviceClaimStore = result.setupStore("blockdeviceclaims")

return result, nil
}
Expand Down Expand Up @@ -293,6 +296,8 @@ func (c *client) clientAndType(resource string) (rest.Interface, interface{}, er
return c.mayaClient.OpenebsV1alpha1().RESTClient(), &mayav1alpha1.CStorPool{}, nil
case "blockdevices":
return c.mayaClient.OpenebsV1alpha1().RESTClient(), &mayav1alpha1.BlockDevice{}, nil
case "blockdeviceclaims":
return c.mayaClient.OpenebsV1alpha1().RESTClient(), &mayav1alpha1.BlockDeviceClaim{}, nil
case "cronjobs":
ok, err := c.isResourceSupported(c.client.BatchV1beta1().RESTClient().APIVersion(), resource)
if err != nil {
Expand Down Expand Up @@ -567,6 +572,16 @@ func (c *client) WalkCStorPools(f func(CStorPool) error) error {
return nil
}

func (c *client) WalkBlockDeviceClaims(f func(BlockDeviceClaim) error) error {
for _, m := range c.blockDeviceClaimStore.List() {
blockDeviceClaim := m.(*mayav1alpha1.BlockDeviceClaim)
if err := f(NewBlockDeviceClaim(blockDeviceClaim)); err != nil {
return err
}
}
return nil
}

func (c *client) CloneVolumeSnapshot(namespaceID, volumeSnapshotID, persistentVolumeClaimID, capacity string) error {
var scName string
var claimSize string
Expand Down
35 changes: 35 additions & 0 deletions probe/kubernetes/controls.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,17 @@ func (r *Reporter) describeBlockDevice(req xfer.Request, namespaceID, blockDevic
return r.describe(req, namespaceID, blockDeviceID, schema.GroupKind{}, restMapping)
}

func (r *Reporter) describeBlockDeviceClaim(req xfer.Request, namespaceID, blockDeviceClaimID string) xfer.Response {
restMapping := apimeta.RESTMapping{
Resource: schema.GroupVersionResource{
Group: OpenEBSGroupName,
Version: OpenEBSVersion,
Resource: "blockdeviceclaims",
},
}
return r.describe(req, namespaceID, blockDeviceClaimID, schema.GroupKind{}, restMapping)
}

// GetLogs is the control to get the logs for a kubernetes pod
func (r *Reporter) describe(req xfer.Request, namespaceID, resourceID string, groupKind schema.GroupKind, restMapping apimeta.RESTMapping) xfer.Response {
readCloser, err := r.client.Describe(namespaceID, resourceID, groupKind, restMapping)
Expand Down Expand Up @@ -290,6 +301,8 @@ func (r *Reporter) Describe() func(xfer.Request) xfer.Response {
f = r.CaptureDisk(r.describeDisk)
case "<block_device>":
f = r.CaptureBlockDevice(r.describeBlockDevice)
case "<block_device_claim>":
f = r.CaptureBlockDeviceClaim(r.describeBlockDeviceClaim)
default:
return xfer.ResponseErrorf("Node not found: %s", req.NodeID)
}
Expand Down Expand Up @@ -686,6 +699,28 @@ func (r *Reporter) CaptureBlockDevice(f func(xfer.Request, string, string) xfer.
}
}

// CaptureBlockDeviceClaim will return name and namespace of block device claim
func (r *Reporter) CaptureBlockDeviceClaim(f func(xfer.Request, string, string) xfer.Response) func(xfer.Request) xfer.Response {
return func(req xfer.Request) xfer.Response {
uid, ok := report.ParseBlockDeviceClaimNodeID(req.NodeID)
if !ok {
return xfer.ResponseErrorf("Invalid ID: %s", req.NodeID)
}
// find blockDeviceClaim by UID
var blockDeviceClaim BlockDeviceClaim
r.client.WalkBlockDeviceClaims(func(b BlockDeviceClaim) error {
if b.UID() == uid {
blockDeviceClaim = b
}
return nil
})
if blockDeviceClaim == nil {
return xfer.ResponseErrorf("Block Device Claim not found: %s", uid)
}
return f(req, blockDeviceClaim.Namespace(), blockDeviceClaim.Name())
}
}

// ScaleUp is the control to scale up a deployment
func (r *Reporter) ScaleUp(req xfer.Request, namespace, id string) xfer.Response {
return xfer.ResponseError(r.client.ScaleUp(namespace, id))
Expand Down
31 changes: 30 additions & 1 deletion probe/kubernetes/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const (
PercentEnduranceUsed = report.KubernetesPercentEnduranceUsed
BlockDeviceList = report.KubernetesBlockDeviceList
Path = report.KubernetesPath
BlockDeviceName = report.KubernetesBlockDeviceName
)

var (
Expand Down Expand Up @@ -254,11 +255,20 @@ var (
VolumeName: {ID: CStorVolumeReplicaName, Label: "CStor Volume Replica", From: report.FromLatest, Priority: 2},
Status: {ID: Status, Label: "Status", From: report.FromLatest, Priority: 3},
}

CStorPoolMetadataTemplates = report.MetadataTemplates{
NodeType: {ID: NodeType, Label: "Type", From: report.FromLatest, Priority: 1},
VolumeName: {ID: CStorPoolName, Label: "CStor Pool", From: report.FromLatest, Priority: 2},
Status: {ID: Status, Label: "Status", From: report.FromLatest, Priority: 3},
}

BlockDeviceClaimMetadataTemplates = report.MetadataTemplates{
NodeType: {ID: NodeType, Label: "Type", From: report.FromLatest, Priority: 1},
BlockDeviceName: {ID: BlockDeviceName, Label: "Block device name", From: report.FromLatest, Priority: 2},
HostName: {ID: HostName, Label: "Host", From: report.FromLatest, Priority: 3},
Status: {ID: Status, Label: "Status", From: report.FromLatest, Priority: 4},
}

TableTemplates = report.TableTemplates{
LabelPrefix: {
ID: LabelPrefix,
Expand Down Expand Up @@ -489,6 +499,10 @@ func (r *Reporter) Report() (report.Report, error) {
if err != nil {
return result, err
}
blockDeviceClaimTopology, _, err := r.blockDeviceClaimTopology()
if err != nil {
return result, err
}
result.Pod = result.Pod.Merge(podTopology)
result.Service = result.Service.Merge(serviceTopology)
result.DaemonSet = result.DaemonSet.Merge(daemonSetTopology)
Expand All @@ -508,6 +522,7 @@ func (r *Reporter) Report() (report.Report, error) {
result.CStorVolumeReplica = result.CStorVolumeReplica.Merge(cStorVolumeReplicaTopology)
result.CStorPool = result.CStorPool.Merge(cStorPoolTopology)
result.BlockDevice = result.BlockDevice.Merge(blockDeviceTopology)
result.BlockDeviceClaim = result.BlockDeviceClaim.Merge(blockDeviceClaimTopology)
return result, nil
}

Expand Down Expand Up @@ -658,7 +673,7 @@ func (r *Reporter) volumeSnapshotTopology() (report.Topology, []VolumeSnapshot,
Human: "Delete",
Category: report.AdminControl,
Icon: "far fa-trash-alt",
Rank: 1,
Rank: 3,
})
result.Controls.AddControl(DescribeControl)
err := r.client.WalkVolumeSnapshots(func(p VolumeSnapshot) error {
Expand Down Expand Up @@ -782,6 +797,20 @@ func (r *Reporter) cStorPoolTopology() (report.Topology, []CStorPool, error) {
return result, cStorPool, err
}

func (r *Reporter) blockDeviceClaimTopology() (report.Topology, []BlockDeviceClaim, error) {
blockDeviceClaims := []BlockDeviceClaim{}
result := report.MakeTopology().
WithMetadataTemplates(BlockDeviceClaimMetadataTemplates).
WithTableTemplates(TableTemplates)
result.Controls.AddControl(DescribeControl)
err := r.client.WalkBlockDeviceClaims(func(p BlockDeviceClaim) error {
result.AddNode(p.GetNode(r.probeID))
blockDeviceClaims = append(blockDeviceClaims, p)
return nil
})
return result, blockDeviceClaims, err
}

type labelledChild interface {
Labels() map[string]string
AddParent(string, string)
Expand Down
3 changes: 3 additions & 0 deletions probe/kubernetes/reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ func (c *mockClient) WalkCStorPools(f func(kubernetes.CStorPool) error) error {
func (c *mockClient) WalkBlockDevices(f func(kubernetes.BlockDevice) error) error {
return nil
}
func (c *mockClient) WalkBlockDeviceClaims(f func(kubernetes.BlockDeviceClaim) error) error {
return nil
}
func (*mockClient) WatchPods(func(kubernetes.Event, kubernetes.Pod)) {}
func (c *mockClient) GetLogs(namespaceID, podName string, _ []string) (io.ReadCloser, error) {
r, ok := c.logs[namespaceID+";"+podName]
Expand Down
7 changes: 7 additions & 0 deletions render/detailed/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,13 @@ var nodeSummaryGroupSpecs = []struct {
Columns: []Column{},
},
},
{
topologyID: report.BlockDeviceClaim,
NodeSummaryGroup: NodeSummaryGroup{
Label: "Block Device Claim",
Columns: []Column{},
},
},
}

func children(rc RenderContext, n report.Node) []NodeSummaryGroup {
Expand Down
8 changes: 8 additions & 0 deletions render/detailed/summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ var renderers = map[string]func(BasicNodeSummary, report.Node) BasicNodeSummary{
report.CStorVolume: cStorVolumeNodeSummary,
report.CStorVolumeReplica: cStorVolumeReplicaNodeSummary,
report.CStorPool: cStorPoolNodeSummary,
report.BlockDeviceClaim: blockDeviceClaimNodeSummary,
}

// For each report.Topology, map to a 'primary' API topology. This can then be used in a variety of places.
Expand Down Expand Up @@ -126,6 +127,7 @@ var primaryAPITopology = map[string]string{
report.CStorVolumeReplica: "volumes",
report.CStorPool: "volumes",
report.BlockDevice: "pools",
report.BlockDeviceClaim: "pools",
}

// MakeBasicNodeSummary returns a basic summary of a node, if
Expand Down Expand Up @@ -471,6 +473,12 @@ func cStorPoolNodeSummary(base BasicNodeSummary, n report.Node) BasicNodeSummary
return base
}

func blockDeviceClaimNodeSummary(base BasicNodeSummary, n report.Node) BasicNodeSummary {
base = addKubernetesLabelAndRank(base, n)
base.LabelMinor = "Block Device Claim"
return base
}

// groupNodeSummary renders the summary for a group node. n.Topology is
// expected to be of the form: group:container:hostname
func groupNodeSummary(base BasicNodeSummary, r report.Report, n report.Node) BasicNodeSummary {
Expand Down
2 changes: 2 additions & 0 deletions render/filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var storageComponents = map[string]string{
"disk": "disk",
"volume_snapshot": "volume_snapshot",
"volume_snapshot_data": "volume_snapshot_data",
"block_device_claim": "block_device_claim",
}

var cStorComponents = map[string]string{
Expand All @@ -32,6 +33,7 @@ var cStorComponents = map[string]string{
"cstor_pool": "cstor_pool",
"block_device": "block_device",
"disk": "disk",
"block_device_claim": "block_device_claim",
}

// CustomRenderer allow for mapping functions that received the entire topology
Expand Down
1 change: 1 addition & 0 deletions render/persistentvolume.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var KubernetesVolumesRenderer = MakeReduce(
PVToControllerRenderer,
VolumeSnapshotRenderer,
CSPToBdOrDiskRenderer,
BlockDeviceClaimToBlockDeviceRenderer,
BlockDeviceToDiskRenderer,
MakeFilter(
func(n report.Node) bool {
Expand Down
1 change: 1 addition & 0 deletions render/selectors.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ var (
SelectDisk = TopologySelector(report.Disk)
SelectBlockDevice = TopologySelector(report.BlockDevice)
SelectStoragePoolClaim = TopologySelector(report.StoragePoolClaim)
SelectBlockDeviceClaim = TopologySelector(report.BlockDeviceClaim)
)
26 changes: 26 additions & 0 deletions render/storagerenderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
var KubernetesStorageRenderer = MakeReduce(
SPCToCSPRenderer,
CSPToBdOrDiskRenderer,
BlockDeviceClaimToBlockDeviceRenderer,
BlockDeviceToDiskRenderer,
)

Expand Down Expand Up @@ -120,3 +121,28 @@ func (b blockDeviceToDiskRenderer) Render(ctx context.Context, rpt report.Report
}
return Nodes{Nodes: nodes}
}

// BlockDeviceClaimToBlockDeviceRenderer is a renderer which produces renderable k8s object of block device claim.
var BlockDeviceClaimToBlockDeviceRenderer blockDeviceClaimToBlockDeviceRenderer

// blockDeviceClaimToBlockDeviceRenderer is a renderer to render BDC and BD.
type blockDeviceClaimToBlockDeviceRenderer struct{}

func (b blockDeviceClaimToBlockDeviceRenderer) Render(ctx context.Context, rpt report.Report) Nodes {
nodes := make(report.Nodes)
for bdcID, bdcNode := range rpt.BlockDeviceClaim.Nodes {
bdcNamespace, _ := bdcNode.Latest.Lookup(kubernetes.Namespace)
bdNameFromBdc, _ := bdcNode.Latest.Lookup(kubernetes.BlockDeviceName)
for bdID, bdNode := range rpt.BlockDevice.Nodes {
bdName, _ := bdNode.Latest.Lookup(kubernetes.Name)
bdNamespace, _ := bdNode.Latest.Lookup(kubernetes.Namespace)
if bdName == bdNameFromBdc && bdNamespace == bdcNamespace {
bdcNode.Adjacency = bdcNode.Adjacency.Add(bdID)
bdcNode.Children = bdcNode.Children.Add(bdNode)
break
}
}
nodes[bdcID] = bdcNode
}
return Nodes{Nodes: nodes}
}
6 changes: 6 additions & 0 deletions report/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,12 @@ var (

// ParseCStorPoolNodeID parses a CStor Volume node ID
ParseCStorPoolNodeID = parseSingleComponentID("cstor_pool")

// MakeBlockDeviceClaimNodeID produces a block device claim node ID from its composite parts.
MakeBlockDeviceClaimNodeID = makeSingleComponentID("block_device_claim")

// ParseBlockDeviceClaimNodeID parses a block device claim node ID
ParseBlockDeviceClaimNodeID = parseSingleComponentID("block_device_claim")
)

// makeSingleComponentID makes a single-component node id encoder
Expand Down
1 change: 1 addition & 0 deletions report/map_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ const (
KubernetesStorage = "kubernetes_storage"
KubernetesBlockDeviceList = "kubernetes_block_device_list"
KubernetesPath = "kubernetes_path"
KubernetesBlockDeviceName = "kubernetes_block_device_name"
// probe/awsecs
ECSCluster = "ecs_cluster"
ECSCreatedAt = "ecs_created_at"
Expand Down
Loading

0 comments on commit f0fa228

Please sign in to comment.