1#!/usr/bin/env python3 2# SPDX-License-Identifier: BSD-3-Clause 3# Copyright (C) 2018 Intel Corporation 4# All rights reserved. 5# 6 7import os 8import sys 9import argparse 10import logging 11import spdk.rpc as rpc 12from spdk.rpc.client import print_dict, JSONRPCException 13 14 15def get_bdev_name_key(bdev): 16 bdev_name_key = 'name' 17 if 'method' in bdev and bdev['method'] == 'bdev_split_create': 18 bdev_name_key = "base_bdev" 19 return bdev_name_key 20 21 22def get_bdev_name(bdev): 23 bdev_name = None 24 if 'params' in bdev: 25 if 'name' in bdev['params']: 26 bdev_name = bdev['params']['name'] 27 elif 'base_name' in bdev['params']: 28 bdev_name = bdev['params']['base_name'] 29 elif 'base_bdev' in bdev['params']: 30 bdev_name = bdev['params']['base_bdev'] 31 if 'method' in bdev and bdev['method'] == 'bdev_error_create': 32 bdev_name = "EE_%s" % bdev_name 33 return bdev_name 34 35 36def get_bdev_delete_method(bdev): 37 delete_method_map = {'bdev_malloc_create': "bdev_malloc_delete", 38 'bdev_null_create': "bdev_null_delete", 39 'bdev_rbd_create': "bdev_rbd_delete", 40 'bdev_aio_create': "bdev_aio_delete", 41 'bdev_error_create': "bdev_error_delete", 42 'bdev_split_create': "bdev_split_delete", 43 'bdev_virtio_attach_controller': "bdev_virtio_detach_controller", 44 'bdev_crypto_create': "bdev_crypto_delete", 45 'bdev_delay_create': "bdev_delay_delete", 46 'bdev_passthru_create': "bdev_passthru_delete", 47 'bdev_compress_create': 'bdev_compress_delete', 48 } 49 destroy_method = None 50 if 'method' in bdev: 51 construct_method = bdev['method'] 52 if construct_method in list(delete_method_map.keys()): 53 destroy_method = delete_method_map[construct_method] 54 55 return destroy_method 56 57 58def clear_bdev_subsystem(args, bdev_config): 59 rpc_bdevs = args.client.call("bdev_get_bdevs") 60 for bdev in bdev_config: 61 bdev_name_key = get_bdev_name_key(bdev) 62 bdev_name = get_bdev_name(bdev) 63 destroy_method = get_bdev_delete_method(bdev) 64 if destroy_method: 65 args.client.call(destroy_method, {bdev_name_key: bdev_name}) 66 67 nvme_controllers = args.client.call("bdev_nvme_get_controllers") 68 for ctrlr in nvme_controllers: 69 args.client.call('bdev_nvme_detach_controller', {'name': ctrlr['name']}) 70 71 ''' Disable and reset hotplug ''' 72 rpc.bdev.bdev_nvme_set_hotplug(args.client, False) 73 74 75def get_nvmf_destroy_method(nvmf): 76 delete_method_map = {'nvmf_create_subsystem': "nvmf_delete_subsystem"} 77 try: 78 return delete_method_map[nvmf['method']] 79 except KeyError: 80 return None 81 82 83def clear_nvmf_subsystem(args, nvmf_config): 84 for nvmf in nvmf_config: 85 destroy_method = get_nvmf_destroy_method(nvmf) 86 if destroy_method: 87 args.client.call(destroy_method, {'nqn': nvmf['params']['nqn']}) 88 89 90def get_iscsi_destroy_method(iscsi): 91 delete_method_map = {'iscsi_create_portal_group': "iscsi_delete_portal_group", 92 'iscsi_create_initiator_group': "iscsi_delete_initiator_group", 93 'iscsi_create_target_node': "iscsi_delete_target_node", 94 'iscsi_set_options': None 95 } 96 return delete_method_map[iscsi['method']] 97 98 99def get_iscsi_name(iscsi): 100 if 'name' in iscsi['params']: 101 return iscsi['params']['name'] 102 else: 103 return iscsi['params']['tag'] 104 105 106def get_iscsi_name_key(iscsi): 107 if iscsi['method'] == 'iscsi_create_target_node': 108 return "name" 109 else: 110 return 'tag' 111 112 113def clear_iscsi_subsystem(args, iscsi_config): 114 for iscsi in iscsi_config: 115 destroy_method = get_iscsi_destroy_method(iscsi) 116 if destroy_method: 117 args.client.call(destroy_method, {get_iscsi_name_key(iscsi): get_iscsi_name(iscsi)}) 118 119 120def get_nbd_destroy_method(nbd): 121 delete_method_map = {'nbd_start_disk': "nbd_stop_disk" 122 } 123 return delete_method_map[nbd['method']] 124 125 126def clear_nbd_subsystem(args, nbd_config): 127 for nbd in nbd_config: 128 destroy_method = get_nbd_destroy_method(nbd) 129 if destroy_method: 130 args.client.call(destroy_method, {'nbd_device': nbd['params']['nbd_device']}) 131 132 133def get_ublk_destroy_method(ublk): 134 delete_method_map = {'ublk_start_disk': "ublk_stop_disk"} 135 return delete_method_map[ublk['method']] 136 137 138def clear_ublk_subsystem(args, ublk_config): 139 for ublk in ublk_config: 140 destroy_method = get_ublk_destroy_method(ublk) 141 if destroy_method: 142 args.client.call(destroy_method, {'ublk_device': ublk['params']['ublk_device']}) 143 144 145def clear_vhost_scsi_subsystem(args, vhost_config): 146 for vhost in reversed(vhost_config): 147 if 'method' in vhost: 148 method = vhost['method'] 149 if method in ['vhost_scsi_controller_add_target']: 150 args.client.call("vhost_scsi_controller_remove_target", 151 {"ctrlr": vhost['params']['ctrlr'], 152 "scsi_target_num": vhost['params']['scsi_target_num']}) 153 elif method in ['vhost_create_scsi_controller']: 154 args.client.call("vhost_delete_controller", {'ctrlr': vhost['params']['ctrlr']}) 155 156 157def clear_vhost_blk_subsystem(args, vhost_config): 158 for vhost in reversed(vhost_config): 159 if 'method' in vhost: 160 method = vhost['method'] 161 if method in ['vhost_create_blk_controller']: 162 args.client.call("vhost_delete_controller", {'ctrlr': vhost['params']['ctrlr']}) 163 164 165def call_test_cmd(func): 166 def rpc_test_cmd(*args, **kwargs): 167 try: 168 func(*args, **kwargs) 169 except JSONRPCException as ex: 170 print((ex.message)) 171 exit(1) 172 return rpc_test_cmd 173 174 175if __name__ == "__main__": 176 parser = argparse.ArgumentParser(description='Clear config command') 177 parser.add_argument('-s', dest='server_addr', default='/var/tmp/spdk.sock') 178 parser.add_argument('-p', dest='port', default=5260, type=int) 179 parser.add_argument('-t', dest='timeout', default=60.0, type=float) 180 parser.add_argument('-v', dest='verbose', action='store_const', const="INFO", 181 help='Set verbose mode to INFO', default="ERROR") 182 parser.add_argument('--verbose', dest='verbose', choices=['DEBUG', 'INFO', 'ERROR'], 183 help="""Set verbose level. """) 184 subparsers = parser.add_subparsers(help='RPC methods') 185 186 @call_test_cmd 187 def clear_config(args): 188 for subsystem_item in reversed(args.client.call('framework_get_subsystems')): 189 args.subsystem = subsystem_item['subsystem'] 190 clear_subsystem(args) 191 192 p = subparsers.add_parser('clear_config', help="""Clear configuration of all SPDK subsystems and targets using JSON RPC""") 193 p.set_defaults(func=clear_config) 194 195 @call_test_cmd 196 def clear_subsystem(args): 197 config = args.client.call('framework_get_config', {"name": args.subsystem}) 198 if config is None: 199 return 200 method = globals().get(f'clear_{args.subsystem}_subsystem') 201 if method is not None: 202 if args.verbose: 203 print(f'Calling {method.__name__}') 204 method(args, config) 205 206 p = subparsers.add_parser('clear_subsystem', help="""Clear configuration of SPDK subsystem using JSON RPC""") 207 p.add_argument('--subsystem', help="""Subsystem name""") 208 p.set_defaults(func=clear_subsystem) 209 210 args = parser.parse_args() 211 212 with rpc.client.JSONRPCClient(args.server_addr, args.port, args.timeout, log_level=getattr(logging, args.verbose.upper())) as client: 213 try: 214 args.client = client 215 args.func(args) 216 except JSONRPCException as ex: 217 print((ex.message)) 218 exit(1) 219