Skip to content

Commit 3934c4c

Browse files
authored
Merge pull request #893 from gbregman/devel
Implement namespace netmask
2 parents 010aabb + 34fd029 commit 3934c4c

File tree

15 files changed

+608
-49
lines changed

15 files changed

+608
-49
lines changed

.github/workflows/build-container.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ jobs:
299299
if: success() || failure()
300300
run: make top
301301

302-
- name: Test
302+
- name: Test ${{ matrix.security_protocol }}
303303
run: |
304304
./tests/ha/demo_test.sh test_${{ matrix.security_protocol }}
305305
@@ -328,11 +328,11 @@ jobs:
328328
with:
329329
files: "/tmp/coredump/core.*"
330330

331-
- name: Upload demo core dumps
331+
- name: Upload demo-${{ matrix.security_protocol }} core dumps
332332
if: steps.check_coredumps.outputs.files_exists == 'true'
333333
uses: actions/upload-artifact@v4
334334
with:
335-
name: core_demo
335+
name: core_demo_${{ matrix.security_protocol }}
336336
path: /tmp/coredump/core.*
337337

338338
# For debugging purposes (provides an SSH connection to the runner)

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ up:
6262

6363
clean: $(CLEAN) setup ## Clean-up environment
6464
clean: override HUGEPAGES = 0
65+
clean:
66+
/usr/bin/rm -f control/proto/gateway_pb2_grpc.py control/proto/gateway_pb2.py control/proto/gateway_pb2.pyi control/proto/monitor_pb2_grpc.py control/proto/monitor_pb2.py control/proto/monitor_pb2.pyi
6567

6668
update-lockfile: run ## Update dependencies in lockfile (pdm.lock)
6769
update-lockfile: SVC=nvmeof-builder-base

ceph-nvmeof.conf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ enable_spdk_discovery_controller = False
2929
#verify_nqns = True
3030
#allowed_consecutive_spdk_ping_failures = 1
3131
#spdk_ping_interval_in_seconds = 2.0
32+
#max_hosts_per_namespace = 1
33+
#max_namespaces_with_netmask = 1000
3234

3335
[gateway-logs]
3436
log_level=debug

control/cli.py

Lines changed: 122 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,9 +1067,7 @@ def host_add(self, args):
10671067
if not args.dhchap_key:
10681068
self.cli.parser.error(f"DH-HMAC-CHAP controller keys can not be used without DH-HMAC-CHAP keys")
10691069

1070-
for i in range(len(args.host_nqn)):
1071-
one_host_nqn = args.host_nqn[i]
1072-
1070+
for one_host_nqn in args.host_nqn:
10731071
if one_host_nqn == "*" and args.psk:
10741072
self.cli.parser.error(f"PSK key is only allowed for specific hosts")
10751073

@@ -1360,7 +1358,8 @@ def ns_add(self, args):
13601358
anagrpid=args.load_balancing_group,
13611359
create_image=args.rbd_create_image,
13621360
size=img_size,
1363-
force=args.force)
1361+
force=args.force,
1362+
no_auto_visible=args.no_auto_visible)
13641363
try:
13651364
ret = self.stub.namespace_add(req)
13661365
except Exception as ex:
@@ -1547,6 +1546,15 @@ def ns_list(self, args):
15471546
lb_group = "<n/a>"
15481547
else:
15491548
lb_group = str(ns.load_balancing_group)
1549+
if ns.no_auto_visible:
1550+
if len(ns.hosts) > 0:
1551+
for hst in ns.hosts:
1552+
visibility = break_string(hst, ":", 2) + "\n"
1553+
else:
1554+
visibility = "Selective"
1555+
else:
1556+
visibility = "All Hosts"
1557+
15501558
namespaces_list.append([ns.nsid,
15511559
break_string(ns.bdev_name, "-", 2),
15521560
ns.rbd_pool_name,
@@ -1555,6 +1563,7 @@ def ns_list(self, args):
15551563
self.format_size(ns.block_size),
15561564
break_string(ns.uuid, "-", 3),
15571565
lb_group,
1566+
visibility,
15581567
self.get_qos_limit_str_value(ns.rw_ios_per_second),
15591568
self.get_qos_limit_str_value(ns.rw_mbytes_per_second),
15601569
self.get_qos_limit_str_value(ns.r_mbytes_per_second),
@@ -1567,7 +1576,7 @@ def ns_list(self, args):
15671576
table_format = "plain"
15681577
namespaces_out = tabulate(namespaces_list,
15691578
headers = ["NSID", "Bdev\nName", "RBD\nPool", "RBD\nImage",
1570-
"Image\nSize", "Block\nSize", "UUID", "Load\nBalancing\nGroup",
1579+
"Image\nSize", "Block\nSize", "UUID", "Load\nBalancing\nGroup", "Visibility",
15711580
"R/W IOs\nper\nsecond", "R/W MBs\nper\nsecond",
15721581
"Read MBs\nper\nsecond", "Write MBs\nper\nsecond"],
15731582
tablefmt=table_format)
@@ -1809,6 +1818,98 @@ def ns_set_qos(self, args):
18091818

18101819
return ret.status
18111820

1821+
def ns_add_host(self, args):
1822+
"""Adds a host to a namespace."""
1823+
1824+
rc = 0
1825+
ret_list = []
1826+
out_func, err_func = self.get_output_functions(args)
1827+
1828+
if args.nsid <= 0:
1829+
self.cli.parser.error("nsid value must be positive")
1830+
1831+
for one_host_nqn in args.host_nqn:
1832+
try:
1833+
add_host_req = pb2.namespace_add_host_req(subsystem_nqn=args.subsystem, nsid=args.nsid, host_nqn=one_host_nqn)
1834+
ret = self.stub.namespace_add_host(add_host_req)
1835+
except Exception as ex:
1836+
ret = pb2.req_status(status = errno.EINVAL, error_message = f"Failure adding host to namespace:\n{ex}")
1837+
1838+
if not rc:
1839+
rc = ret.status
1840+
1841+
if args.format == "text" or args.format == "plain":
1842+
if ret.status == 0:
1843+
out_func(f"Adding host {one_host_nqn} to namespace {args.nsid} on {args.subsystem}: Successful")
1844+
else:
1845+
err_func(f"{ret.error_message}")
1846+
elif args.format == "json" or args.format == "yaml":
1847+
ret_str = json_format.MessageToJson(
1848+
ret,
1849+
indent=4,
1850+
including_default_value_fields=True,
1851+
preserving_proto_field_name=True)
1852+
if args.format == "json":
1853+
out_func(f"{ret_str}")
1854+
elif args.format == "yaml":
1855+
obj = json.loads(ret_str)
1856+
out_func(yaml.dump(obj))
1857+
elif args.format == "python":
1858+
ret_list.append(ret)
1859+
else:
1860+
assert False
1861+
1862+
if args.format == "python":
1863+
return ret_list
1864+
1865+
return rc
1866+
1867+
def ns_del_host(self, args):
1868+
"""Deletes a host from a namespace."""
1869+
1870+
rc = 0
1871+
ret_list = []
1872+
out_func, err_func = self.get_output_functions(args)
1873+
1874+
if args.nsid <= 0:
1875+
self.cli.parser.error("nsid value must be positive")
1876+
1877+
for one_host_nqn in args.host_nqn:
1878+
try:
1879+
del_host_req = pb2.namespace_delete_host_req(subsystem_nqn=args.subsystem, nsid=args.nsid, host_nqn=one_host_nqn)
1880+
ret = self.stub.namespace_delete_host(del_host_req)
1881+
except Exception as ex:
1882+
ret = pb2.req_status(status = errno.EINVAL, error_message = f"Failure deleting host from namespace:\n{ex}")
1883+
1884+
if not rc:
1885+
rc = ret.status
1886+
1887+
if args.format == "text" or args.format == "plain":
1888+
if ret.status == 0:
1889+
out_func(f"Deleting host {args.host_nqn} from namespace {args.nsid} on {args.subsystem}: Successful")
1890+
else:
1891+
err_func(f"{ret.error_message}")
1892+
elif args.format == "json" or args.format == "yaml":
1893+
ret_str = json_format.MessageToJson(
1894+
ret,
1895+
indent=4,
1896+
including_default_value_fields=True,
1897+
preserving_proto_field_name=True)
1898+
if args.format == "json":
1899+
out_func(f"{ret_str}")
1900+
elif args.format == "yaml":
1901+
obj = json.loads(ret_str)
1902+
out_func(yaml.dump(obj))
1903+
elif args.format == "python":
1904+
ret_list.append(ret)
1905+
else:
1906+
assert False
1907+
1908+
if args.format == "python":
1909+
return ret_list
1910+
1911+
return rc
1912+
18121913
ns_common_args = [
18131914
argument("--subsystem", "-n", help="Subsystem NQN", required=True),
18141915
]
@@ -1821,7 +1922,8 @@ def ns_set_qos(self, args):
18211922
argument("--block-size", "-s", help="Block size", type=int),
18221923
argument("--load-balancing-group", "-l", help="Load balancing group", type=int, default=0),
18231924
argument("--size", help="Size in bytes or specified unit (K, KB, M, MB, G, GB, T, TB, P, PB)"),
1824-
argument("--force", help="Create a namespace even its image is already used by another namespace", action='store_true', required=False),
1925+
argument("--force", help="Create a namespace even when its image is already used by another namespace", action='store_true', required=False),
1926+
argument("--no-auto-visible", help="Make the namespace visible only to specific hosts", action='store_true', required=False),
18251927
]
18261928
ns_del_args_list = ns_common_args + [
18271929
argument("--nsid", help="Namespace ID", type=int, required=True),
@@ -1848,6 +1950,14 @@ def ns_set_qos(self, args):
18481950
argument("--r-megabytes-per-second", help="Read megabytes per second limit, 0 means unlimited", type=int),
18491951
argument("--w-megabytes-per-second", help="Write megabytes per second limit, 0 means unlimited", type=int),
18501952
]
1953+
ns_add_host_args_list = ns_common_args + [
1954+
argument("--nsid", help="Namespace ID", type=int, required=True),
1955+
argument("--host-nqn", "-t", help="Host NQN list", nargs="+", required=True),
1956+
]
1957+
ns_del_host_args_list = ns_common_args + [
1958+
argument("--nsid", help="Namespace ID", type=int, required=True),
1959+
argument("--host-nqn", "-t", help="Host NQN list", nargs="+", required=True),
1960+
]
18511961
ns_actions = []
18521962
ns_actions.append({"name" : "add", "args" : ns_add_args_list, "help" : "Create a namespace"})
18531963
ns_actions.append({"name" : "del", "args" : ns_del_args_list, "help" : "Delete a namespace"})
@@ -1856,6 +1966,8 @@ def ns_set_qos(self, args):
18561966
ns_actions.append({"name" : "get_io_stats", "args" : ns_get_io_stats_args_list, "help" : "Get I/O stats for a namespace"})
18571967
ns_actions.append({"name" : "change_load_balancing_group", "args" : ns_change_load_balancing_group_args_list, "help" : "Change load balancing group for a namespace"})
18581968
ns_actions.append({"name" : "set_qos", "args" : ns_set_qos_args_list, "help" : "Set QOS limits for a namespace"})
1969+
ns_actions.append({"name" : "add_host", "args" : ns_add_host_args_list, "help" : "Add a host to a namespace"})
1970+
ns_actions.append({"name" : "del_host", "args" : ns_del_host_args_list, "help" : "Delete a host from a namespace"})
18591971
ns_choices = get_actions(ns_actions)
18601972
@cli.cmd(ns_actions, ["ns"])
18611973
def namespace(self, args):
@@ -1874,6 +1986,10 @@ def namespace(self, args):
18741986
return self.ns_change_load_balancing_group(args)
18751987
elif args.action == "set_qos":
18761988
return self.ns_set_qos(args)
1989+
elif args.action == "add_host":
1990+
return self.ns_add_host(args)
1991+
elif args.action == "del_host":
1992+
return self.ns_del_host(args)
18771993
if not args.action:
18781994
self.cli.parser.error(f"missing action for namespace command (choose from {GatewayClient.ns_choices})")
18791995

0 commit comments

Comments
 (0)