spdkcli: add basic vhost management
Adding: - listing current vhost scsi and blk configuration - add / remove scsi and blk controllers - modify scsi targets and luns - set controller coalescing Change-Id: If00d820d03731f1110f665b14258617d917b9bfd Signed-off-by: Karol Latecki <karol.latecki@intel.com> Signed-off-by: Pawel Kaminski <pawelx.kaminski@intel.com> Reviewed-on: https://review.gerrithub.io/406538 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
This commit is contained in:
parent
fdd6dbc902
commit
5e5cc5ac9c
@ -477,3 +477,191 @@ class UILvsObj(UINode):
|
|||||||
free = "=".join(["Free", free])
|
free = "=".join(["Free", free])
|
||||||
info = ", ".join([str(size), str(free)])
|
info = ", ".join([str(size), str(free)])
|
||||||
return info, True
|
return info, True
|
||||||
|
|
||||||
|
|
||||||
|
class UIVhosts(UINode):
|
||||||
|
def __init__(self, parent):
|
||||||
|
UINode.__init__(self, "vhost", parent)
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
self._children = set([])
|
||||||
|
self.get_root().list_vhost_ctrls()
|
||||||
|
UIVhostBlk(self)
|
||||||
|
UIVhostScsi(self)
|
||||||
|
|
||||||
|
|
||||||
|
class UIVhost(UINode):
|
||||||
|
def __init__(self, name, parent):
|
||||||
|
UINode.__init__(self, name, parent)
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
|
def ui_command_delete(self, name):
|
||||||
|
"""
|
||||||
|
Delete a Vhost controller from configuration.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
name - Controller name.
|
||||||
|
"""
|
||||||
|
self.get_root().remove_vhost_controller(ctrlr=name)
|
||||||
|
self.get_root().refresh()
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
|
|
||||||
|
class UIVhostBlk(UIVhost):
|
||||||
|
def __init__(self, parent):
|
||||||
|
UIVhost.__init__(self, "block", parent)
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
self._children = set([])
|
||||||
|
for ctrlr in self.get_root().get_vhost_ctrlrs(self.name):
|
||||||
|
UIVhostBlkCtrlObj(ctrlr, self)
|
||||||
|
|
||||||
|
def ui_command_create(self, name, bdev, cpumask=None, readonly=False):
|
||||||
|
"""
|
||||||
|
Construct a Vhost BLK controller.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
name - Controller name.
|
||||||
|
bdev - Which bdev to attach to the controller.
|
||||||
|
cpumask - Optional. Integer to specify mask of CPUs to use.
|
||||||
|
Default: 1.
|
||||||
|
readonly - Whether controller should be read only or not.
|
||||||
|
Default: False.
|
||||||
|
"""
|
||||||
|
ret_name = self.get_root().create_vhost_blk_controller(ctrlr=name,
|
||||||
|
dev_name=bdev,
|
||||||
|
cpumask=cpumask,
|
||||||
|
readonly=bool(readonly))
|
||||||
|
self.get_root().refresh()
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
|
|
||||||
|
class UIVhostScsi(UIVhost):
|
||||||
|
def __init__(self, parent):
|
||||||
|
UIVhost.__init__(self, "scsi", parent)
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
self._children = set([])
|
||||||
|
for ctrlr in self.get_root().get_vhost_ctrlrs(self.name):
|
||||||
|
UIVhostScsiCtrlObj(ctrlr, self)
|
||||||
|
|
||||||
|
def ui_command_create(self, name, cpumask=None):
|
||||||
|
"""
|
||||||
|
Construct a Vhost SCSI controller.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
name - Controller name.
|
||||||
|
cpumask - Optional. Integer to specify mask of CPUs to use.
|
||||||
|
Default: 1.
|
||||||
|
"""
|
||||||
|
ret_name = self.get_root().create_vhost_scsi_controller(ctrlr=name,
|
||||||
|
cpumask=cpumask)
|
||||||
|
self.get_root().refresh()
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
|
|
||||||
|
class UIVhostCtrl(UINode):
|
||||||
|
# Base class for SCSI and BLK controllers, do not instantiate
|
||||||
|
def __init__(self, ctrlr, parent):
|
||||||
|
self.ctrlr = ctrlr
|
||||||
|
UINode.__init__(self, self.ctrlr.ctrlr, parent)
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
|
def ui_command_show_details(self):
|
||||||
|
self.shell.log.info(json.dumps(vars(self.ctrlr), indent=2))
|
||||||
|
|
||||||
|
def ui_command_set_coalescing(self, delay_base_us, iops_threshold):
|
||||||
|
delay_base_us = self.ui_eval_param(delay_base_us, "number", None)
|
||||||
|
iops_threshold = self.ui_eval_param(iops_threshold, "number", None)
|
||||||
|
self.get_root().set_vhost_controller_coalescing(ctrlr=self.ctrlr.ctrlr,
|
||||||
|
delay_base_us=delay_base_us,
|
||||||
|
iops_threshold=iops_threshold)
|
||||||
|
|
||||||
|
|
||||||
|
class UIVhostScsiCtrlObj(UIVhostCtrl):
|
||||||
|
def refresh(self):
|
||||||
|
self._children = set([])
|
||||||
|
for lun in self.ctrlr.backend_specific["scsi"]:
|
||||||
|
UIVhostTargetObj(lun, self)
|
||||||
|
|
||||||
|
def ui_command_remove_target(self, target_num):
|
||||||
|
"""
|
||||||
|
Remove target node from SCSI controller.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
target_num - Integer identifier of target node to delete.
|
||||||
|
"""
|
||||||
|
self.get_root().remove_vhost_scsi_target(ctrlr=self.ctrlr.ctrlr,
|
||||||
|
scsi_target_num=int(target_num))
|
||||||
|
for ctrlr in self.get_root().get_vhost_ctrlrs("scsi"):
|
||||||
|
if ctrlr.ctrlr == self.ctrlr.ctrlr:
|
||||||
|
self.ctrlr = ctrlr
|
||||||
|
|
||||||
|
self.refresh()
|
||||||
|
self.get_root().refresh()
|
||||||
|
|
||||||
|
def ui_command_add_lun(self, target_num, bdev_name):
|
||||||
|
"""
|
||||||
|
Add LUN to SCSI target node.
|
||||||
|
Currently only one LUN (which is LUN ID 0) per target is supported.
|
||||||
|
Adding LUN to not existing target node will create that node.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
target_num - Integer identifier of target node to modify.
|
||||||
|
bdev - Which bdev to add as LUN.
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.get_root().add_vhost_scsi_lun(ctrlr=self.ctrlr.ctrlr,
|
||||||
|
scsi_target_num=int(target_num),
|
||||||
|
bdev_name=bdev_name)
|
||||||
|
for ctrlr in self.get_root().get_vhost_ctrlrs("scsi"):
|
||||||
|
if ctrlr.ctrlr == self.ctrlr.ctrlr:
|
||||||
|
self.ctrlr = ctrlr
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
|
def summary(self):
|
||||||
|
info = self.ctrlr.socket
|
||||||
|
return info, True
|
||||||
|
|
||||||
|
|
||||||
|
class UIVhostBlkCtrlObj(UIVhostCtrl):
|
||||||
|
def refresh(self):
|
||||||
|
self._children = set([])
|
||||||
|
UIVhostLunDevObj(self.ctrlr.backend_specific["block"]["bdev"], self)
|
||||||
|
|
||||||
|
def summary(self):
|
||||||
|
ro = None
|
||||||
|
if self.ctrlr.backend_specific["block"]["readonly"]:
|
||||||
|
ro = "Readonly"
|
||||||
|
info = ", ".join(filter(None, [self.ctrlr.socket, ro]))
|
||||||
|
return info, True
|
||||||
|
|
||||||
|
|
||||||
|
class UIVhostTargetObj(UINode):
|
||||||
|
def __init__(self, target, parent):
|
||||||
|
self.target = target
|
||||||
|
# Next line: configshell does not allow paths with spaces.
|
||||||
|
UINode.__init__(self, target["target_name"].replace(" ", "_"), parent)
|
||||||
|
self.refresh()
|
||||||
|
|
||||||
|
def refresh(self):
|
||||||
|
self._children = set([])
|
||||||
|
for target in self.target["luns"]:
|
||||||
|
UIVhostLunDevObj(target["bdev_name"], self)
|
||||||
|
|
||||||
|
def ui_command_show_details(self):
|
||||||
|
self.shell.log.info(json.dumps(self.target, indent=2))
|
||||||
|
|
||||||
|
def summary(self):
|
||||||
|
luns = "LUNs: %s" % len(self.target["luns"])
|
||||||
|
id = "TargetID: %s" % self.target["scsi_dev_num"]
|
||||||
|
info = ",".join([luns, id])
|
||||||
|
return info, True
|
||||||
|
|
||||||
|
|
||||||
|
class UIVhostLunDevObj(UINode):
|
||||||
|
def __init__(self, name, parent):
|
||||||
|
UINode.__init__(self, name, parent)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from .ui_node import UINode, UIBdevs, UILvolStores
|
from .ui_node import UINode, UIBdevs, UILvolStores, UIVhosts
|
||||||
import rpc.client
|
import rpc.client
|
||||||
import rpc
|
import rpc
|
||||||
|
|
||||||
@ -11,12 +11,14 @@ class UIRoot(UINode):
|
|||||||
UINode.__init__(self, "/", shell=shell)
|
UINode.__init__(self, "/", shell=shell)
|
||||||
self.current_bdevs = []
|
self.current_bdevs = []
|
||||||
self.current_lvol_stores = []
|
self.current_lvol_stores = []
|
||||||
|
self.current_vhost_ctrls = []
|
||||||
self.set_rpc_target(s)
|
self.set_rpc_target(s)
|
||||||
|
|
||||||
def refresh(self):
|
def refresh(self):
|
||||||
self._children = set([])
|
self._children = set([])
|
||||||
UIBdevs(self)
|
UIBdevs(self)
|
||||||
UILvolStores(self)
|
UILvolStores(self)
|
||||||
|
UIVhosts(self)
|
||||||
|
|
||||||
def set_rpc_target(self, s):
|
def set_rpc_target(self, s):
|
||||||
self.client = rpc.client.JSONRPCClient(s)
|
self.client = rpc.client.JSONRPCClient(s)
|
||||||
@ -121,6 +123,37 @@ class UIRoot(UINode):
|
|||||||
response = rpc.bdev.construct_rbd_bdev(self.client, **kwargs)
|
response = rpc.bdev.construct_rbd_bdev(self.client, **kwargs)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def list_vhost_ctrls(self):
|
||||||
|
self.current_vhost_ctrls = rpc.vhost.get_vhost_controllers(self.client)
|
||||||
|
|
||||||
|
def get_vhost_ctrlrs(self, ctrlr_type):
|
||||||
|
for ctrlr in filter(lambda x: ctrlr_type in x["backend_specific"].keys(),
|
||||||
|
self.current_vhost_ctrls):
|
||||||
|
yield VhostCtrlr(ctrlr)
|
||||||
|
|
||||||
|
def remove_vhost_controller(self, **kwargs):
|
||||||
|
rpc.vhost.remove_vhost_controller(self.client, **kwargs)
|
||||||
|
self.current_vhost_ctrls = rpc.vhost.get_vhost_controllers(self.client)
|
||||||
|
|
||||||
|
def create_vhost_scsi_controller(self, **kwargs):
|
||||||
|
rpc.vhost.construct_vhost_scsi_controller(self.client, **kwargs)
|
||||||
|
self.current_vhost_ctrls = rpc.vhost.get_vhost_controllers(self.client)
|
||||||
|
|
||||||
|
def create_vhost_blk_controller(self, **kwargs):
|
||||||
|
rpc.vhost.construct_vhost_blk_controller(self.client, **kwargs)
|
||||||
|
self.current_vhost_ctrls = rpc.vhost.get_vhost_controllers(self.client)
|
||||||
|
|
||||||
|
def remove_vhost_scsi_target(self, **kwargs):
|
||||||
|
rpc.vhost.remove_vhost_scsi_target(self.client, **kwargs)
|
||||||
|
self.current_vhost_ctrls = rpc.vhost.get_vhost_controllers(self.client)
|
||||||
|
|
||||||
|
def add_vhost_scsi_lun(self, **kwargs):
|
||||||
|
rpc.vhost.add_vhost_scsi_lun(self.client, **kwargs)
|
||||||
|
self.current_vhost_ctrls = rpc.vhost.get_vhost_controllers(self.client)
|
||||||
|
|
||||||
|
def set_vhost_controller_coalescing(self, **kwargs):
|
||||||
|
rpc.vhost.set_vhost_controller_coalescing(self.client, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Bdev(object):
|
class Bdev(object):
|
||||||
def __init__(self, bdev_info):
|
def __init__(self, bdev_info):
|
||||||
@ -144,3 +177,15 @@ class LvolStore(object):
|
|||||||
"""
|
"""
|
||||||
for i in lvs_info.keys():
|
for i in lvs_info.keys():
|
||||||
setattr(self, i, lvs_info[i])
|
setattr(self, i, lvs_info[i])
|
||||||
|
|
||||||
|
|
||||||
|
class VhostCtrlr(object):
|
||||||
|
def __init__(self, ctrlr_info):
|
||||||
|
"""
|
||||||
|
All class attributes are set based on what information is received
|
||||||
|
from get_vhost_controllers RPC call.
|
||||||
|
# TODO: Document in docstring parameters which describe bdevs.
|
||||||
|
# TODO: Possible improvement: JSON schema might be used here in future
|
||||||
|
"""
|
||||||
|
for i in ctrlr_info.keys():
|
||||||
|
setattr(self, i, ctrlr_info[i])
|
||||||
|
Loading…
Reference in New Issue
Block a user