Skip to content

Commit

Permalink
util: enhance tracevol.py script to work with volumesnapshots
Browse files Browse the repository at this point in the history
This patch adds the functionality to map the k8s volumesnapshots
to the cephfs/rbd snapshots.

This patch also adds a wrapper around oc/kubectl called `kube_client`
which will help get rid of code duplication.

Closes: #3344

Signed-off-by: Niraj Yadav <[email protected]>
  • Loading branch information
black-dragon74 committed Jan 2, 2025
1 parent 18a62ec commit 5ff5ab6
Showing 1 changed file with 75 additions and 0 deletions.
75 changes: 75 additions & 0 deletions troubleshooting/tools/tracevol.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,80 @@ def get_fsname_from_pvdata(arg, pvdata):
sys.exit()
return fsname

def kube_client(*commands):
"""
Executes a Kubernetes or OpenShift command with the provided arguments and returns the JSON output.
Note: Do not pass `-o json` as an argument, this helper adds it automatically.
Example:
kube_client("get", "pvcs")
Args:
*commands: Additional command-line arguments to pass to the Kubernetes or OpenShift command.
"""
arg = ARGS
cmd = [arg.command]
if arg.kubeconfig != "":
cmd += ["--kubeconfig", arg.kubeconfig]
cmd += ["--namespace", arg.namespace]
cmd += filter(lambda x: x != "-o" and x != "json", commands)
cmd += ["-o", "json"]

with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as out:
stdout, stderr = out.communicate()

if stderr is not None:
if arg.debug:
print("failed to execute command {} due to {}".format(commands, stderr))
sys.exit()
try:
data = json.loads(stdout)
except ValueError as err:
print(err, stdout)
sys.exit()

return data

def parse_volume_snapshots(volsnapshots):
"""
Parses a list of volume snapshots and prints a table with their details.
"""
snapshot_table = prettytable.PrettyTable()
snapshot_table.title = "Volume Snapshots"
snapshot_table.field_names = ["Name", "PVC", "PVC Type", "Subvolume Name", "Snapshot ID"]

for snapshot in volsnapshots['items']:
snap_name = snapshot['metadata']['name']
pvc_name = snapshot['spec']['source']['persistentVolumeClaimName']

# Fetch the PVC and its PV, useful later
pvc = kube_client("get", "pvc", pvc_name)
pv_data = kube_client("get", "pv", pvc['spec']['volumeName'])

# Find the type of the PVC (RBD or CephFS)
fs_type = "CephFS" if "fsName" in pv_data['spec']['csi']['volumeAttributes'] else "RBD"

# Get the vol name inside ceph
prefix = get_volname_prefix(ARGS, pv_data)
imgID = prefix + get_image_uuid(pv_data['spec']['csi']['volumeHandle'])

# Get the snapshot ID, we can inspect volumesnapshotcontent to get the snapshot handle
# Alternatively, we can use the toolbox pod to fetch these values from ceph directly
snap_content_name = snapshot['status']['boundVolumeSnapshotContentName']
snap_content = kube_client("get", "volumesnapshotcontent", snap_content_name)
snap_id = "csi-snap-" + get_image_uuid(snap_content['status']['snapshotHandle'])

snapshot_table.add_row([snap_name, pvc_name, fs_type, imgID, snap_id])

print(snapshot_table)

def list_volume_snapshots():
"""
Retrieve and parse the list of volume snapshots from the cluster.
"""
volumesnapshots = kube_client("get", "volumesnapshots")
parse_volume_snapshots(volumesnapshots)

if __name__ == "__main__":
ARGS = PARSER.parse_args()
if ARGS.command not in ["kubectl", "oc"]:
Expand All @@ -571,3 +645,4 @@ def get_fsname_from_pvdata(arg, pvdata):
print("python version less than 3 is not supported.")
sys.exit(1)
list_pvc_vol_name_mapping(ARGS)
list_volume_snapshots()

0 comments on commit 5ff5ab6

Please sign in to comment.