From edcad79429fed4cfdccedcdd7657ad982eee6b88 Mon Sep 17 00:00:00 2001 From: Guillaume Date: Mon, 11 Sep 2023 15:02:00 +0200 Subject: [PATCH] Add kalray plugin to configure DPU - Work is in progress and not ready for reviewing... - Just add three functions to check that we can do the RPC - Need to add creation of lvols Signed-off-by: Guillaume --- README.md | 68 +++++++++++++ SOURCES/etc/xapi.d/plugins/kalray_dpu.py | 119 +++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100755 SOURCES/etc/xapi.d/plugins/kalray_dpu.py diff --git a/README.md b/README.md index a8e8385..048643c 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,74 @@ $ xe host-call-plugin host-uuid= plugin=zfs.py fn=list_zfs_pools ``` (the most pertinent parameter is `mountpoint`) +## XCP-ng Kalray DPU + +A xapi plugin to get information about raids, logical volume store (LVS) and +devices that are present on the Kalray DPU. It also allow the management of +logical volumes (LV): creation and deletion. Parameters depends of the name of +the command some are always available: + - *username*: username to use to connect to DPU (required) + - *password*: password to connect to DPU (required) + - *server*: IP of the server for configuring the DPU (default: localhost) + - *port*: Port to use (default: 8080) + - *timeout*: timeout in second (default: 60.0) + +## Command details + +### Block devices +#### Get the list of devices on the Kalray DPU +``` +$ xe host-call-plugin host-uuid= plugin=kalray_dpu.py fn=get_devices \ + args:username= args:password= +{"status": "ok", "output": [{"name": "HotInNvmeWDS500AFY0-22050C800415n1", "aliases": [], "product_name": "NVMe disk", "block_size": 512, "num_blocks": 976773168, "uuid": "e8238fa6-bf53-0001-001b-448b45afa6a7", "assigned_rate_limits": {"rw_ios_per_sec": 0, "rw_mbytes_per_sec": 0, "r_mbytes_per_sec": 0, "w_mbytes_per_sec": 0}, "claimed": false, "zoned": false, "supported_io_types": {"read": true, "write": true, "unmap": true, "write_zeroes": true, "flush": true, "reset": true, "nvme_admin": true, "nvme_io": true}, "driver_specific": {"nvme": [{"pci_address": "0000:00:00.0", "trid": {"trtype": "PCIe", "traddr": "0000:00:00.0"}, "ctrlr_data": {"cntlid": 8224, "vendor_id": "0x15b7", "model_number": "WDS500G1X0E-00AFY0", "serial_number": "22050C800415", "firmware_revision": "614900WD", "subnqn": "nqn.2018-01.com.wdc:nguid:E8238FA6BF53-0001-001B448B45AFA6A7", "oacs": {"security": 1, "format": 1, "firmware": 1, "ns_manage": 0}, "multi_ctrlr": false, "ana_reporting": false}, "vs": {"nvme_version": "1.4"}, "ns_data": {"id": 1, "can_share": false}, "security": {"opal": false}}], "mp_policy": "active_passive"}}]} +``` + +### RAID +#### Create a raid on the Kalray DPU +``` +$ xe host-call-plugin host-uuid= plugin=kalray_dpu.py fn=create_raid \ + args:username= args:password= +[...] +``` + +#### Get the list of raids on the Kalray DPU +``` +$ xe host-call-plugin host-uuid= plugin=kalray_dpu.py fn=get_raids \ + args:username= args:password= +[...] +``` + +### Logical Volume Store +#### Create an LVS on the Kalray DPU +``` +$ xe host-call-plugin host-uuid= plugin=kalray_dpu.py fn=create_lvs \ + args:username= args:password= +[...] +``` + +#### Get the list of LVS on the Kalray DPU +``` +$ xe host-call-plugin host-uuid= plugin=kalray_dpu.py fn=get_lvs \ + args:username= args:password= +[...] +``` + +### Logical Volume +#### Create a new logical volume +``` +$ xe host-call-plugin host-uuid= plugin=kalray_dpu.py fn=create_lvol \ + args:username= args:password= +[...] +``` + +#### Delete a logical volume +``` +$ xe host-call-plugin host-uuid= plugin=kalray_dpu.py fn=delete_lvol \ + args:username= args:password= \ + args:name= +[...] +``` + ## XCP-ng LVM A xapi plugin to list, create and destroy PVs, VGs and LVMs on a host. diff --git a/SOURCES/etc/xapi.d/plugins/kalray_dpu.py b/SOURCES/etc/xapi.d/plugins/kalray_dpu.py new file mode 100755 index 0000000..634167f --- /dev/null +++ b/SOURCES/etc/xapi.d/plugins/kalray_dpu.py @@ -0,0 +1,119 @@ +#!/usr/bin/python3 +"""XAPI plugin to manage Kalray DPU.""" + +import json +import XenAPIPlugin # pylint: disable=import-error + +from kalray.acs.spdk import rpc # pylint: disable=import-error +from xcpngutils import error_wrapped + +class PluginOutput: + def _to_json(status: bool, string: str): + """Return the status and the string as a json.""" + return json.dumps({ + 'success': status, + 'response': string, + }) + + def success(msg): + return PluginOutput._to_json(True, msg) + + def failure(msg): + return PluginOutput._to_json(False, msg) + + +class KalrayCmd: + """Describe a command to be ran on the Kalray DPU.""" + + def __init__(self, rpc_name: str, updates: dict): + self.server = 'localhost' + self.port = 8080 + self.username = None + self.password = None + self.timeout = 60.0 + self.rpc_name = rpc_name + self.rpc_params = {} + + for k, v in updates.items(): + if hasattr(self, k): + setattr(self, k, v) + + # Check that username & password are well set + assert self.username is not None + assert self.password is not None + + def add_rpc_params(self, key: str, value: str): + """Adds a parameter that will be passed to the RPC.""" + self.rpc_params[key] = value + + def call_rpc(self): + """Do the RPC call.""" + try: + client = rpc.client.HTTPJSONRPCClient( + self.server, + self.port, + self.timeout, + self.username, + self.password, + log_level="ERROR") + message = client.call(self.rpc_name, self.rpc_params) + except rpc.client.JSONRPCException as exc: + return PluginOutput.failure(exc.message) + else: + return PluginOutput.success(message) + +@error_wrapped +def get_devices(_session, args): + """Get the list of devices available on the Kalray DPU.""" + kc = KalrayCmd('bdev_get_bdevs', args) + return kc.call_rpc() + +@error_wrapped +def create_raid(_session, args): + """Create a raid.""" + kc = KalrayCmd('bdev_raid_create', args) + return PluginOutput.failure("Creation of raid is not yet implemented") + +@error_wrapped +def get_raids(_session, args): + """Get the list of raids available on the Kalray DPU.""" + kc = KalrayCmd('bdev_raid_get_bdevs', args) + kc.add_rpc_params('category', 'all') + return kc.call_rpc() + +@error_wrapped +def create_lvs(_session, args): + """Create a logical volume store.""" + kc = KalrayCmd('bdev_lvol_create_lvstore', args) + return PluginOutput.failure("Creation of lvs is not yet implemented") + +@error_wrapped +def get_lvs(_session, args): + """Get the list of logical volume stores available on the Kalray DPU.""" + kc = KalrayCmd('bdev_lvol_get_lvstores', args) + return kc.call_rpc() + +@error_wrapped +def create_lvol(_session, _args): + """Create a new lvol on the Kalray DPU.""" + return PluginOutput.failure("Creation of lvol is not yet implemented") + +@error_wrapped +def delete_lvol(_session, args): + """Delete the lvol passed as parameter on the Kalray DPU if exists.""" + try: + lvol_name = args["name"] + return PluginOutput.failure(f"Deletion of lvol {lvol_name} is not yet implemented") + except KeyError as exc: + raise RuntimeError("No argument found with key 'name'.") from exc + +if __name__ == "__main__": + XenAPIPlugin.dispatch({ + "get_devices": get_devices, + "create_raid": create_raid, + "get_raids": get_raids, + "create_lvol": create_lvs, + "get_lvs": get_lvs, + "create_lvol": create_lvol, + "delete_lvol": delete_lvol, + })