{"id":22499737,"url":"https://github.com/opiproject/opi-spdk-bridge","last_synced_at":"2025-08-20T02:32:31.382Z","repository":{"id":61808185,"uuid":"555094219","full_name":"opiproject/opi-spdk-bridge","owner":"opiproject","description":"OPI Storage gRPC to SPDK json-rpc bridge","archived":false,"fork":false,"pushed_at":"2024-08-02T21:46:13.000Z","size":2073,"stargazers_count":8,"open_issues_count":49,"forks_count":13,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-11-17T04:45:06.823Z","etag":null,"topics":["dpu","golang","grpc","json","opi","rpc","spdk","storage"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/opiproject.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-21T00:04:33.000Z","updated_at":"2024-09-06T03:08:20.000Z","dependencies_parsed_at":"2022-10-21T14:45:30.363Z","dependency_job_id":"ca06d2d4-cac9-448b-bda4-7a8035e5b444","html_url":"https://github.com/opiproject/opi-spdk-bridge","commit_stats":{"total_commits":472,"total_committers":14,"mean_commits":"33.714285714285715","dds":0.5508474576271186,"last_synced_commit":"42326c8dfe8a539d9fb2ec370fd51ba9d182344b"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opiproject%2Fopi-spdk-bridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opiproject%2Fopi-spdk-bridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opiproject%2Fopi-spdk-bridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opiproject%2Fopi-spdk-bridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/opiproject","download_url":"https://codeload.github.com/opiproject/opi-spdk-bridge/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230388129,"owners_count":18217755,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dpu","golang","grpc","json","opi","rpc","spdk","storage"],"created_at":"2024-12-06T22:15:36.694Z","updated_at":"2024-12-19T06:08:43.071Z","avatar_url":"https://github.com/opiproject.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OPI storage gRPC to SPDK json-rpc bridge\n\n[![Linters](https://github.com/opiproject/opi-spdk-bridge/actions/workflows/linters.yml/badge.svg)](https://github.com/opiproject/opi-spdk-bridge/actions/workflows/linters.yml)\n[![CodeQL](https://github.com/opiproject/opi-spdk-bridge/actions/workflows/codeql.yml/badge.svg)](https://github.com/opiproject/opi-spdk-bridge/actions/workflows/codeql.yml)\n[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/opiproject/opi-spdk-bridge/badge)](https://securityscorecards.dev/viewer/?platform=github.com\u0026org=opiproject\u0026repo=opi-spdk-bridge)\n[![tests](https://github.com/opiproject/opi-spdk-bridge/actions/workflows/docker-publish.yml/badge.svg)](https://github.com/opiproject/opi-spdk-bridge/actions/workflows/docker-publish.yml)\n[![License](https://img.shields.io/github/license/opiproject/opi-spdk-bridge?style=flat-square\u0026color=blue\u0026label=License)](https://github.com/opiproject/opi-spdk-bridge/blob/master/LICENSE)\n[![codecov](https://codecov.io/gh/opiproject/opi-spdk-bridge/branch/main/graph/badge.svg)](https://codecov.io/gh/opiproject/opi-spdk-bridge)\n[![Go Report Card](https://goreportcard.com/badge/github.com/opiproject/opi-spdk-bridge)](https://goreportcard.com/report/github.com/opiproject/opi-spdk-bridge)\n[![Go Doc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/opiproject/opi-spdk-bridge)\n[![Last Release](https://img.shields.io/github/v/release/opiproject/opi-spdk-bridge?label=Latest\u0026style=flat-square\u0026logo=go)](https://github.com/opiproject/opi-spdk-bridge/releases)\n[![GitHub stars](https://img.shields.io/github/stars/opiproject/opi-spdk-bridge.svg?style=flat-square\u0026label=github%20stars)](https://github.com/opiproject/opi-spdk-bridge)\n[![GitHub Contributors](https://img.shields.io/github/contributors/opiproject/opi-spdk-bridge.svg?style=flat-square)](https://github.com/opiproject/opi-spdk-bridge/graphs/contributors)\n\nThis is a simple SPDK based storage API PoC.\n\n* SPDK - container with SPDK app that is running on xPU\n* Server - container with OPI gRPC storage APIs to SPDK json-rpc APIs bridge\n* Client - use [goDPU](https://github.com/opiproject/godpu) for testing of the above server/bridge\n\n## I Want To Contribute\n\nThis project welcomes contributions and suggestions.  We are happy to have the Community involved via submission of **Issues and Pull Requests** (with substantive content or even just fixes). We are hoping for the documents, test framework, etc. to become a community process with active engagement.  PRs can be reviewed by by any number of people, and a maintainer may accept.\n\nSee [CONTRIBUTING](https://github.com/opiproject/opi/blob/main/CONTRIBUTING.md) and [GitHub Basic Process](https://github.com/opiproject/opi/blob/main/doc-github-rules.md) for more details.\n\n## Docs\n\n* [JSON RPC Proxy](https://spdk.io/doc/jsonrpc_proxy.html)\n* [SPDK SMA](https://github.com/spdk/spdk/tree/master/python/spdk/sma)\n* [SPDK CSI](https://github.com/spdk/spdk-csi/blob/master/deploy/spdk/Dockerfile)\n* [CSI Spec](https://github.com/container-storage-interface/spec/blob/master/spec.md)\n\n## OPI-SPDK Bridge Block Diagram\n\nThe following is the example architecture we envision for the OPI Storage\nSPDK bridge APIs. It utilizes SPDK to handle storage services,\nand the configuration is handled by standard JSON-RPC based APIs\nsee \u003chttps://spdk.io/doc/jsonrpc.html\u003e\n\nWe recongnise, not all companies use SPDK, so for them only PROTOBUF definitions\nare going to be the OPI conumable product. For those that wish to use SPDK, this\nis a refernce implementation not intended to use in production.\n\n![OPI Storage SPDK bridge/server](doc/OPI-storage-SPDK-bridge.png)\n\n## OPI-SPDK Bridge Sequence Diagram\n\nThe following is the example sequence diagram for OPI-SPDK bridge APIs.\nIt is just an example and implies SPDK just as example, not mandated by OPI.\n\n![OPI Storage SPDK bridge/server](doc/OPI-Storage-Sequence.png)\n\n## Getting started\n\n:exclamation: `docker-compose` is deprecated. For details, see [Migrate to Compose V2](https://docs.docker.com/compose/migrate/).\n\n* [Setup everything once using ansible](https://github.com/opiproject/opi-poc/tree/main/setup)\n* Run `docker compose up -d` or `docker-compose up -d`\n\n## QEMU example\n\n* [OPI Storage QEMU SPDK Setup](doc/qemu_spdk_setup.md)\n* [SPDK vhost-user Target Overview](doc/vhost_user.md)\n\n## Real DPU/IPU example\n\non DPU/IPU (i.e. with IP=10.10.10.10) run\n\n```bash\n$ docker run --rm -it -v /var/tmp/:/var/tmp/ -p 50051:50051 -p 8082:8082 ghcr.io/opiproject/opi-spdk-bridge:main\n2023/09/12 20:29:05 Connection to SPDK will be via: unix detected from /var/tmp/spdk.sock\n2023/09/12 20:29:05 gRPC server listening at [::]:50051\n2023/09/12 20:29:05 HTTP Server listening at 8082\n```\n\non X86 management VM run either gRPC or HTTP requests\n\n```bash\n# gRPC requests\ndocker run --network=host --rm -it namely/grpc-cli ls   --json_input --json_output 10.10.10.10:50051 -l\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 CreateNvmeSubsystem \"{nvme_subsystem : {spec : {nqn: 'nqn.2022-09.io.spdk:opitest2', serial_number: 'myserial2', model_number: 'mymodel2', max_namespaces: 11} }, nvme_subsystem_id : 'subsystem2' }\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 ListNvmeSubsystems \"{}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 GetNvmeSubsystem \"{name : 'nvmeSubsystems/subsystem2'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 CreateNvmeController \"{parent: 'nvmeSubsystems/subsystem2', nvme_controller : {spec : {nvme_controller_id: 2, pcie_id : {physical_function : 0, virtual_function : 0, port_id: 0}, max_nsq:5, max_ncq:5, 'trtype': 'NVME_TRANSPORT_TYPE_PCIE' } }, nvme_controller_id : 'controller1'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 CreateNvmeSubsystem \"{nvme_subsystem : {spec : {nqn: 'nqn.2022-09.io.spdk:opitest3', serial_number: 'myserial2', model_number: 'mymodel2', max_namespaces: 11} }, nvme_subsystem_id : 'subsystem3' }\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 CreateNvmeController \"{'parent':'nvmeSubsystems/subsystem3','nvme_controller':{'spec':{'nvme_controller_id':2,'fabrics_id':{'traddr': '127.0.0.1', trsvcid: '4421', adrfam: 'NVME_ADDRESS_FAMILY_IPV4'}, 'max_nsq':5,'max_ncq':5, 'trtype': 'NVME_TRANSPORT_TYPE_TCP'}},'nvme_controller_id':'controller3'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 ListNvmeControllers \"{parent : 'nvmeSubsystems/subsystem2'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 GetNvmeController \"{name : 'nvmeSubsystems/subsystem2/nvmeControllers/controller1'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 GetNvmeController \"{name : 'nvmeSubsystems/subsystem3/nvmeControllers/controller3'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 CreateNvmeNamespace \"{parent: 'nvmeSubsystems/subsystem2', nvme_namespace : {spec : {volume_name_ref : 'Malloc0', 'host_nsid' : '10', uuid:{value : '1b4e28ba-2fa1-11d2-883f-b9a761bde3fb'}, nguid: '1b4e28ba-2fa1-11d2-883f-b9a761bde3fb', eui64: 1967554867335598546 } }, nvme_namespace_id: 'namespace1'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 ListNvmeNamespaces \"{parent : 'nvmeSubsystems/subsystem2'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 GetNvmeNamespace \"{name : 'nvmeSubsystems/subsystem2/nvmeNamespaces/namespace1'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 StatsNvmeNamespace \"{name : 'nvmeSubsystems/subsystem2/nvmeNamespaces/namespace1'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 CreateNvmeRemoteController \"{nvme_remote_controller : {multipath: 'NVME_MULTIPATH_MULTIPATH', tcp: {hdgst: false, ddgst: false}}, nvme_remote_controller_id: 'nvmetcp12'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 ListNvmeRemoteControllers \"{}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 GetNvmeRemoteController \"{name: 'nvmeRemoteControllers/nvmetcp12'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 CreateNvmePath \"{parent: 'nvmeRemoteControllers/nvmetcp12', nvme_path : {traddr:'11.11.11.2', trtype:'NVME_TRANSPORT_TYPE_TCP', fabrics:{subnqn:'nqn.2016-06.com.opi.spdk.target0', trsvcid:'4444', adrfam:'NVME_ADDRESS_FAMILY_IPV4', hostnqn:'nqn.2014-08.org.nvmexpress:uuid:feb98abe-d51f-40c8-b348-2753f3571d3c'}}, nvme_path_id: 'nvmetcp12path0'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 CreateNvmeRemoteController \"{nvme_remote_controller : {multipath: 'NVME_MULTIPATH_DISABLE'}, nvme_remote_controller_id: 'nvmepcie13'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 CreateNvmePath \"{parent: 'nvmeRemoteControllers/nvmepcie13', nvme_path : {traddr:'0000:01:00.0', trtype:'NVME_TRANSPORT_TYPE_PCIE'}, nvme_path_id: 'nvmepcie13path0'}\"\n\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 ListNvmePaths \"{parent : 'nvmeRemoteControllers/nvmepcie13'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 DeleteNvmePath \"{name: 'nvmeRemoteControllers/nvmepcie13/nvmePaths/nvmepcie13path0'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 DeleteNvmeRemoteController \"{name: 'nvmeRemoteControllers/nvmepcie13'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 GetNvmePath \"{name: 'nvmeRemoteControllers/nvmetcp12/nvmePaths/nvmetcp12path0'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 DeleteNvmePath \"{name: 'nvmeRemoteControllers/nvmetcp12/nvmePaths/nvmetcp12path0'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 DeleteNvmeRemoteController \"{name: 'nvmeRemoteControllers/nvmetcp12'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 DeleteNvmeNamespace \"{name : 'nvmeSubsystems/subsystem2/nvmeNamespaces/namespace1'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 DeleteNvmeController \"{name : 'nvmeSubsystems/subsystem2/nvmeControllers/controller1'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 DeleteNvmeSubsystem \"{name : 'nvmeSubsystems/subsystem2'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 DeleteNvmeController \"{name : 'nvmeSubsystems/subsystem3/nvmeControllers/controller3'}\"\ndocker run --network=host --rm -it namely/grpc-cli call --json_input --json_output 10.10.10.10:50051 DeleteNvmeSubsystem \"{name : 'nvmeSubsystems/subsystem3'}\"\n```\n\n```bash\n# HTTP requests\n# inventory\ncurl -kL http://10.10.10.10:8082/v1/inventory/1/inventory/2\n\n# Nvme\n# create\ncurl -X POST -f http://10.10.10.10:8082/v1/nvmeRemoteControllers?nvme_remote_controller_id=nvmetcp12 -d '{\"multipath\": \"NVME_MULTIPATH_MULTIPATH\"}'\ncurl -X POST -f http://10.10.10.10:8082/v1/nvmeRemoteControllers/nvmetcp12/nvmePaths?nvme_path_id=nvmetcp12path0 -d '{\"traddr\":\"11.11.11.2\", \"trtype\":\"NVME_TRANSPORT_TYPE_TCP\", \"fabrics\":{\"subnqn\":\"nqn.2016-06.com.opi.spdk.target0\", \"trsvcid\":\"4444\", \"adrfam\":\"NVME_ADDRESS_FAMILY_IPV4\", \"hostnqn\":\"nqn.2014-08.org.nvmexpress:uuid:feb98abe-d51f-40c8-b348-2753f3571d3c\"}}'\ncurl -X POST -f http://10.10.10.10:8082/v1/nvmeSubsystems?nvme_subsystem_id=subsys0 -d '{\"spec\": {\"nqn\": \"nqn.2022-09.io.spdk:opitest1\"}}'\ncurl -X POST -f http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0/nvmeNamespaces?nvme_namespace_id=namespace0 -d '{\"spec\": {\"volume_name_ref\": \"Malloc0\", \"host_nsid\": 10}}'\ncurl -X POST -f http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0/nvmeControllers?nvme_controller_id=ctrl0 -d '{\"spec\": {\"trtype\": \"NVME_TRANSPORT_TYPE_TCP\", \"fabrics_id\":{\"traddr\": \"127.0.0.1\", \"trsvcid\": \"4421\", \"adrfam\": \"NVME_ADDRESS_FAMILY_IPV4\"}}}'\n# get\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeRemoteControllers/nvmetcp12\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeRemoteControllers/nvmetcp12/nvmePaths/nvmetcp12path0\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0/nvmeNamespaces/namespace0\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0/nvmeControllers/ctrl0\n# list\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeRemoteControllers\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeRemoteControllers/nvmetcp12/nvmePaths\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeSubsystems\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0/nvmeNamespaces\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0/nvmeControllers\n# stats\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeRemoteControllers/nvmetcp12:stats\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeRemoteControllers/nvmetcp12/nvmePaths/nvmetcp12path0:stats\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0:stats\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0/nvmeNamespaces/namespace0:stats\ncurl -X GET -f http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0/nvmeControllers/ctrl0:stats\n# update\ncurl -X PATCH -f http://10.10.10.10:8082/v1/nvmeRemoteControllers/nvmetcp12 -d '{\"multipath\": \"NVME_MULTIPATH_MULTIPATH\"}'\ncurl -X PATCH -f http://10.10.10.10:8082/v1/nvmeRemoteControllers/nvmetcp12/nvmePaths/nvmetcp12path0 -d '{\"traddr\":\"11.11.11.2\", \"trtype\":\"NVME_TRANSPORT_TYPE_TCP\", \"fabrics\":{\"subnqn\":\"nqn.2016-06.com.opi.spdk.target0\", \"trsvcid\":\"4444\", \"adrfam\":\"NVME_ADDRESS_FAMILY_IPV4\", \"hostnqn\":\"nqn.2014-08.org.nvmexpress:uuid:feb98abe-d51f-40c8-b348-2753f3571d3c\"}}'\ncurl -X PATCH -k http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0/nvmeNamespaces/namespace0 -d '{\"spec\": {\"volume_name_ref\": \"Malloc1\", \"host_nsid\": 10}}'\ncurl -X PATCH -k http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0/nvmeControllers/ctrl0 -d '{\"spec\": {\"trtype\": \"NVME_TRANSPORT_TYPE_TCP\", \"fabrics_id\":{\"traddr\": \"127.0.0.1\", \"trsvcid\": \"4421\", \"adrfam\": \"NVME_ADDRESS_FAMILY_IPV4\"}}}'\n# delete\ncurl -X DELETE -f http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0/nvmeControllers/ctrl0\ncurl -X DELETE -f http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0/nvmeNamespaces/namespace0\ncurl -X DELETE -f http://10.10.10.10:8082/v1/nvmeSubsystems/subsys0\ncurl -X DELETE -f http://10.10.10.10:8082/v1/nvmeRemoteControllers/nvmetcp12/nvmePaths/nvmetcp12path0\ncurl -X DELETE -f http://10.10.10.10:8082/v1/nvmeRemoteControllers/nvmetcp12\n```\n\n## Test SPDK is up\n\n```bash\ncurl -k --user spdkuser:spdkpass -X POST -H \"Content-Type: application/json\" -d '{\"id\": 1, \"method\": \"bdev_get_bdevs\", \"params\": {\"name\": \"Malloc0\"}}' http://127.0.0.1:9009/\n```\n\n## gRPC CLI examples\n\nFrom \u003chttps://github.com/grpc/grpc-go/blob/master/Documentation/server-reflection-tutorial.md\u003e\n\nAlias\n\n```bash\nalias grpc_cli='docker run --network=opi-spdk-bridge_opi --rm -it namely/grpc-cli'\n```\n\nSee services\n\n```bash\n$ grpc_cli ls opi-spdk-server:50051\ngrpc.reflection.v1alpha.ServerReflection\nopi_api.storage.v1.AioVolumeService\nopi_api.storage.v1.FrontendNvmeService\nopi_api.storage.v1.FrontendVirtioBlkService\nopi_api.storage.v1.FrontendVirtioScsiService\nopi_api.storage.v1.MiddleendEncryptionService\nopi_api.storage.v1.MiddleendQosVolumeService\nopi_api.storage.v1.NvmeRemoteControllerService\nopi_api.storage.v1.NullVolumeService\n```\n\nSee commands\n\n```bash\n$ grpc_cli ls opi-spdk-server:50051 opi_api.storage.v1.FrontendNvmeService -l\nfilename: frontend_nvme_pcie.proto\npackage: opi_api.storage.v1;\nservice FrontendNvmeService {\n  rpc CreateNvmeSubsystem(opi_api.storage.v1.CreateNvmeSubsystemRequest) returns (opi_api.storage.v1.NvmeSubsystem) {}\n  rpc DeleteNvmeSubsystem(opi_api.storage.v1.DeleteNvmeSubsystemRequest) returns (google.protobuf.Empty) {}\n  rpc UpdateNvmeSubsystem(opi_api.storage.v1.UpdateNvmeSubsystemRequest) returns (opi_api.storage.v1.NvmeSubsystem) {}\n  rpc ListNvmeSubsystem(opi_api.storage.v1.ListNvmeSubsystemRequest) returns (opi_api.storage.v1.ListNvmeSubsystemResponse) {}\n  rpc GetNvmeSubsystem(opi_api.storage.v1.GetNvmeSubsystemRequest) returns (opi_api.storage.v1.NvmeSubsystem) {}\n  rpc StatsNvmeSubsystem(opi_api.storage.v1.StatsNvmeSubsystemRequest) returns (opi_api.storage.v1.StatsNvmeSubsystemResponse) {}\n  rpc CreateNvmeController(opi_api.storage.v1.CreateNvmeControllerRequest) returns (opi_api.storage.v1.NvmeController) {}\n  rpc DeleteNvmeController(opi_api.storage.v1.DeleteNvmeControllerRequest) returns (google.protobuf.Empty) {}\n  rpc UpdateNvmeController(opi_api.storage.v1.UpdateNvmeControllerRequest) returns (opi_api.storage.v1.NvmeController) {}\n  rpc ListNvmeController(opi_api.storage.v1.ListNvmeControllerRequest) returns (opi_api.storage.v1.ListNvmeControllerResponse) {}\n  rpc GetNvmeController(opi_api.storage.v1.GetNvmeControllerRequest) returns (opi_api.storage.v1.NvmeController) {}\n  rpc StatsNvmeController(opi_api.storage.v1.StatsNvmeControllerRequest) returns (opi_api.storage.v1.StatsNvmeControllerResponse) {}\n  rpc CreateNvmeNamespace(opi_api.storage.v1.CreateNvmeNamespaceRequest) returns (opi_api.storage.v1.NvmeNamespace) {}\n  rpc DeleteNvmeNamespace(opi_api.storage.v1.DeleteNvmeNamespaceRequest) returns (google.protobuf.Empty) {}\n  rpc UpdateNvmeNamespace(opi_api.storage.v1.UpdateNvmeNamespaceRequest) returns (opi_api.storage.v1.NvmeNamespace) {}\n  rpc ListNvmeNamespace(opi_api.storage.v1.ListNvmeNamespaceRequest) returns (opi_api.storage.v1.ListNvmeNamespaceResponse) {}\n  rpc GetNvmeNamespace(opi_api.storage.v1.GetNvmeNamespaceRequest) returns (opi_api.storage.v1.NvmeNamespace) {}\n  rpc StatsNvmeNamespace(opi_api.storage.v1.StatsNvmeNamespaceRequest) returns (opi_api.storage.v1.StatsNvmeNamespaceResponse) {}\n}\n```\n\nSee methods\n\n```bash\n$ grpc_cli ls opi-spdk-server:50051 opi_api.storage.v1.FrontendNvmeService.CreateNvmeController -l\n  rpc CreateNvmeController(opi_api.storage.v1.CreateNvmeControllerRequest) returns (opi_api.storage.v1.NvmeController) {}\n```\n\nSee messages\n\n```bash\n$ grpc_cli type opi-spdk-server:50051 opi_api.storage.v1.NvmeControllerSpec\nmessage NvmeControllerSpec {\n  .opi_api.common.v1.ObjectKey id = 1 [json_name = \"id\"];\n  int32 nvme_controller_id = 2 [json_name = \"nvmeControllerId\"];\n  .opi_api.common.v1.ObjectKey subsystem_id = 3 [json_name = \"subsystemId\"];\n  .opi_api.storage.v1.PciEndpoint pcie_id = 4 [json_name = \"pcieId\"];\n  int32 max_nsq = 5 [json_name = \"maxNsq\"];\n  int32 max_ncq = 6 [json_name = \"maxNcq\"];\n  int32 sqes = 7 [json_name = \"sqes\"];\n  int32 cqes = 8 [json_name = \"cqes\"];\n  int32 max_namespaces = 9 [json_name = \"maxNamespaces\"];\n}\n\n$ grpc_cli type opi-spdk-server:50051 opi_api.storage.v1.PciEndpoint\nmessage PciEndpoint {\n  int32 port_id = 1 [json_name = \"portId\"];\n  int32 physical_function = 2 [json_name = \"physicalFunction\"];\n  int32 virtual_function = 3 [json_name = \"virtualFunction\"];\n}\n```\n\nCall remote method\n\n```bash\n$ grpc_cli call --json_input --json_output opi-spdk-server:50051 DeleteNvmeController \"{name : 'nvmeSubsystems/subsystem2/nvmeControllers/controller1'}\"\nconnecting to opi-spdk-server:50051\n{}\nRpc succeeded with OK status\n```\n\nServer log\n\n```bash\nopi-spdk-server_1  | 2022/08/05 14:31:14 server listening at [::]:50051\nopi-spdk-server_1  | 2022/08/05 14:39:40 DeleteNvmeSubsystem: Received from client: id:8\nopi-spdk-server_1  | 2022/08/05 14:39:40 Sending to SPDK: {\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"bdev_malloc_delete\",\"params\":{\"name\":\"OpiMalloc8\"}}\nopi-spdk-server_1  | 2022/08/05 14:39:40 Received from SPDK: {1 {-19 No such device} 0xc000029f4e}\nopi-spdk-server_1  | 2022/08/05 14:39:40 error: bdev_malloc_delete: json response error: No such device\nopi-spdk-server_1  | 2022/08/05 14:39:40 Received from SPDK: false\nopi-spdk-server_1  | 2022/08/05 14:39:40 Could not delete: id:8\n```\n\nAnother remote call example\n\n```bash\n$ grpc_cli call --json_input --json_output opi-spdk-server:50051 ListNvmeSubsystem {}\nconnecting to opi-spdk-server:50051\n{\n \"subsystem\": [\n  {\n   \"nqn\": \"nqn.2014-08.org.nvmexpress.discovery\"\n  },\n  {\n   \"nqn\": \"nqn.2016-06.io.spdk:cnode1\"\n  }\n ]\n}\nRpc succeeded with OK status\n```\n\nAnother Server log\n\n```bash\n2022/09/21 19:38:26 ListNvmeSubsystem: Received from client:\n2022/09/21 19:38:26 Sending to SPDK: {\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"bdev_get_bdevs\"}\n2022/09/21 19:38:26 Received from SPDK: {1 {0 } 0x40003de660}\n2022/09/21 19:38:26 Received from SPDK: [{Malloc0 512 131072 08cd0d67-eb57-41c2-957b-585faed7d81a} {Malloc1 512 131072 78c4b40f-dd16-42c1-b057-f95c11db7aaf}]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopiproject%2Fopi-spdk-bridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopiproject%2Fopi-spdk-bridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopiproject%2Fopi-spdk-bridge/lists"}