Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix namespace_resize #449 #756

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 84 additions & 89 deletions control/grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@ def resize_bdev(self, bdev_name, new_size, peer_msg = ""):
self.logger.info(f"Received request to resize bdev {bdev_name} to {new_size} MiB{peer_msg}")
rbd_pool_name = None
rbd_image_name = None
bdev_info = self.get_bdev_info(bdev_name, True)
bdev_info = self.get_bdev_info(bdev_name)
if bdev_info is not None:
try:
drv_specific_info = bdev_info["driver_specific"]
Expand All @@ -382,31 +382,30 @@ def resize_bdev(self, bdev_name, new_size, peer_msg = ""):
self.logger.warning(f"Error trying to get the size of image {rbd_pool_name}/{rbd_image_name}, won't check size for shrinkage:\n{ex}")
pass

with self.rpc_lock:
try:
ret = rpc_bdev.bdev_rbd_resize(
self.spdk_rpc_client,
name=bdev_name,
new_size=new_size,
)
self.logger.debug(f"resize_bdev {bdev_name}: {ret}")
except Exception as ex:
errmsg = f"Failure resizing bdev {bdev_name}"
self.logger.exception(errmsg)
errmsg = f"{errmsg}:\n{ex}"
resp = self.parse_json_exeption(ex)
status = errno.EINVAL
if resp:
status = resp["code"]
errmsg = f"Failure resizing bdev {bdev_name}: {resp['message']}"
return pb2.req_status(status=status, error_message=errmsg)
try:
ret = rpc_bdev.bdev_rbd_resize(
self.spdk_rpc_client,
name=bdev_name,
new_size=new_size,
)
self.logger.debug(f"resize_bdev {bdev_name}: {ret}")
except Exception as ex:
errmsg = f"Failure resizing bdev {bdev_name}"
self.logger.exception(errmsg)
errmsg = f"{errmsg}:\n{ex}"
resp = self.parse_json_exeption(ex)
status = errno.EINVAL
if resp:
status = resp["code"]
errmsg = f"Failure resizing bdev {bdev_name}: {resp['message']}"
return pb2.req_status(status=status, error_message=errmsg)

if not ret:
errmsg = f"Failure resizing bdev {bdev_name}"
self.logger.error(errmsg)
return pb2.req_status(status=errno.EINVAL, error_message=errmsg)
if not ret:
errmsg = f"Failure resizing bdev {bdev_name}"
self.logger.error(errmsg)
return pb2.req_status(status=errno.EINVAL, error_message=errmsg)

return pb2.req_status(status=0, error_message=os.strerror(0))
return pb2.req_status(status=0, error_message=os.strerror(0))

def delete_bdev(self, bdev_name, recycling_mode=False, peer_msg=""):
"""Deletes a bdev."""
Expand Down Expand Up @@ -965,7 +964,7 @@ def namespace_add_safe(self, request, context):
errmsg = f"Failure adding namespace {nsid_msg}to {request.subsystem_nqn}: {ret_bdev.error_message}"
self.logger.error(errmsg)
# Delete the bdev just to be on the safe side
ns_bdev = self.get_bdev_info(bdev_name, False)
ns_bdev = self.get_bdev_info(bdev_name)
if ns_bdev != None:
try:
ret_del = self.delete_bdev(bdev_name, peer_msg = peer_msg)
Expand Down Expand Up @@ -1247,23 +1246,17 @@ def remove_namespace(self, subsystem_nqn, nsid, context):

return pb2.req_status(status=0, error_message=os.strerror(0))

def get_bdev_info(self, bdev_name, need_to_lock):
def get_bdev_info(self, bdev_name):
"""Get bdev info"""

ret_bdev = None
if need_to_lock:
lock_to_use = self.rpc_lock
else:
lock_to_use = contextlib.suppress()

with lock_to_use:
try:
bdevs = rpc_bdev.bdev_get_bdevs(self.spdk_rpc_client, name=bdev_name)
if (len(bdevs) > 1):
self.logger.warning(f"Got {len(bdevs)} bdevs for bdev name {bdev_name}, will use the first one")
ret_bdev = bdevs[0]
except Exception:
self.logger.exception(f"Got exception while getting bdev {bdev_name} info")
try:
bdevs = rpc_bdev.bdev_get_bdevs(self.spdk_rpc_client, name=bdev_name)
if (len(bdevs) > 1):
self.logger.warning(f"Got {len(bdevs)} bdevs for bdev name {bdev_name}, will use the first one")
ret_bdev = bdevs[0]
except Exception:
self.logger.exception(f"Got exception while getting bdev {bdev_name} info")

return ret_bdev

Expand Down Expand Up @@ -1298,63 +1291,63 @@ def list_namespaces(self, request, context=None):
errmsg = f"Failure listing namespaces: {resp['message']}"
return pb2.namespaces_info(status=status, error_message=errmsg, subsystem_nqn=request.subsystem, namespaces=[])

namespaces = []
for s in ret:
try:
if s["nqn"] != request.subsystem:
self.logger.warning(f'Got subsystem {s["nqn"]} instead of {request.subsystem}, ignore')
continue
namespaces = []
for s in ret:
try:
ns_list = s["namespaces"]
except Exception:
ns_list = []
pass
for n in ns_list:
if request.nsid and request.nsid != n["nsid"]:
self.logger.debug(f'Filter out namespace {n["nsid"]} which is different than requested nsid {request.nsid}')
continue
if request.uuid and request.uuid != n["uuid"]:
self.logger.debug(f'Filter out namespace with UUID {n["uuid"]} which is different than requested UUID {request.uuid}')
if s["nqn"] != request.subsystem:
self.logger.warning(f'Got subsystem {s["nqn"]} instead of {request.subsystem}, ignore')
continue
bdev_name = n["bdev_name"]
ns_bdev = self.get_bdev_info(bdev_name, True)
lb_group = 0
try:
lb_group = n["anagrpid"]
except KeyError:
ns_list = s["namespaces"]
except Exception:
ns_list = []
pass
one_ns = pb2.namespace_cli(nsid = n["nsid"],
bdev_name = bdev_name,
uuid = n["uuid"],
load_balancing_group = lb_group)
if ns_bdev == None:
self.logger.warning(f"Can't find namespace's bdev {bdev_name}, will not list bdev's information")
else:
for n in ns_list:
if request.nsid and request.nsid != n["nsid"]:
self.logger.debug(f'Filter out namespace {n["nsid"]} which is different than requested nsid {request.nsid}')
continue
if request.uuid and request.uuid != n["uuid"]:
self.logger.debug(f'Filter out namespace with UUID {n["uuid"]} which is different than requested UUID {request.uuid}')
continue
bdev_name = n["bdev_name"]
ns_bdev = self.get_bdev_info(bdev_name)
lb_group = 0
try:
drv_specific_info = ns_bdev["driver_specific"]
rbd_info = drv_specific_info["rbd"]
one_ns.rbd_image_name = rbd_info["rbd_name"]
one_ns.rbd_pool_name = rbd_info["pool_name"]
one_ns.block_size = ns_bdev["block_size"]
one_ns.rbd_image_size = ns_bdev["block_size"] * ns_bdev["num_blocks"]
assigned_limits = ns_bdev["assigned_rate_limits"]
one_ns.rw_ios_per_second=assigned_limits["rw_ios_per_sec"]
one_ns.rw_mbytes_per_second=assigned_limits["rw_mbytes_per_sec"]
one_ns.r_mbytes_per_second=assigned_limits["r_mbytes_per_sec"]
one_ns.w_mbytes_per_second=assigned_limits["w_mbytes_per_sec"]
except KeyError as err:
self.logger.warning(f"Key {err} is not found, will not list bdev's information")
pass
except Exception:
self.logger.exception(f"{ns_bdev=} parse error")
lb_group = n["anagrpid"]
except KeyError:
pass
namespaces.append(one_ns)
break
except Exception:
self.logger.exception(f"{s=} parse error")
pass
one_ns = pb2.namespace_cli(nsid = n["nsid"],
bdev_name = bdev_name,
uuid = n["uuid"],
load_balancing_group = lb_group)
if ns_bdev == None:
self.logger.warning(f"Can't find namespace's bdev {bdev_name}, will not list bdev's information")
else:
try:
drv_specific_info = ns_bdev["driver_specific"]
rbd_info = drv_specific_info["rbd"]
one_ns.rbd_image_name = rbd_info["rbd_name"]
one_ns.rbd_pool_name = rbd_info["pool_name"]
one_ns.block_size = ns_bdev["block_size"]
one_ns.rbd_image_size = ns_bdev["block_size"] * ns_bdev["num_blocks"]
assigned_limits = ns_bdev["assigned_rate_limits"]
one_ns.rw_ios_per_second=assigned_limits["rw_ios_per_sec"]
one_ns.rw_mbytes_per_second=assigned_limits["rw_mbytes_per_sec"]
one_ns.r_mbytes_per_second=assigned_limits["r_mbytes_per_sec"]
one_ns.w_mbytes_per_second=assigned_limits["w_mbytes_per_sec"]
except KeyError as err:
self.logger.warning(f"Key {err} is not found, will not list bdev's information")
pass
except Exception:
self.logger.exception(f"{ns_bdev=} parse error")
pass
namespaces.append(one_ns)
break
except Exception:
self.logger.exception(f"{s=} parse error")
pass

return pb2.namespaces_info(status = 0, error_message = os.strerror(0), subsystem_nqn=request.subsystem, namespaces=namespaces)
return pb2.namespaces_info(status = 0, error_message = os.strerror(0), subsystem_nqn=request.subsystem, namespaces=namespaces)

def namespace_get_io_stats(self, request, context=None):
"""Get namespace's IO stats."""
Expand Down Expand Up @@ -1617,7 +1610,9 @@ def find_namespace_and_bdev_name(self, nqn, nsid, uuid, needs_lock, err_prefix):

def namespace_resize(self, request, context=None):
"""Resize a namespace."""
return self.execute_grpc_function(self.namespace_resize_safe, request, context)

def namespace_resize_safe(self, request, context=None):
peer_msg = self.get_peer_message(context)
nsid_msg = self.get_ns_id_message(request.nsid, request.uuid)
self.logger.info(f"Received request to resize namespace {nsid_msg}on {request.subsystem_nqn} to {request.new_size} MiB, context: {context}{peer_msg}")
Expand Down
Loading