@@ -52,19 +52,26 @@ def _get_loaded_nvmet_modules():
5252 return output
5353
5454
55- def _runcmd (cmd : list , quiet = False ):
55+ def _runcmd (cmd : list , quiet = False , capture_output = False ):
5656 if not quiet :
5757 print (' ' .join (cmd ))
5858 if args .dry_run :
5959 return
60- subprocess .run (cmd )
60+
61+ try :
62+ cp = subprocess .run (cmd , capture_output = capture_output , text = True )
63+ except TypeError :
64+ # For older Python versions that don't support "capture_output" or "text"
65+ cp = subprocess .run (cmd , stdout = subprocess .PIPE , universal_newlines = True )
66+
67+ return cp .stdout if capture_output else None
6168
6269
6370def _modprobe (module : str , args : list = None , quiet = False ):
6471 cmd = ['/usr/sbin/modprobe' , module ]
6572 if args :
6673 cmd .extend (args )
67- _runcmd (cmd , quiet )
74+ _runcmd (cmd , quiet = quiet )
6875
6976
7077def _mkdir (dname : str ):
@@ -93,12 +100,32 @@ def _symlink(port: str, subsysnqn: str):
93100 link .symlink_to (target )
94101
95102
96- def _create_subsystem (subsysnqn : str ) -> str :
103+ def _symlink_allowed_hosts (hostnqn : str , subsysnqn : str ):
104+ print (
105+ f'$( cd "/sys/kernel/config/nvmet/subsystems/{ subsysnqn } /allowed_hosts" && ln -s "../../../hosts/{ hostnqn } " "{ hostnqn } " )'
106+ )
107+ if args .dry_run :
108+ return
109+ target = os .path .join ('/sys/kernel/config/nvmet/hosts' , hostnqn )
110+ link = pathlib .Path (os .path .join ('/sys/kernel/config/nvmet/subsystems' , subsysnqn , 'allowed_hosts' , hostnqn ))
111+ link .symlink_to (target )
112+
113+
114+ def _create_subsystem (subsysnqn : str , allowed_hosts : list ) -> str :
97115 print (f'###{ Fore .GREEN } Create subsystem: { subsysnqn } { Style .RESET_ALL } ' )
98116 dname = os .path .join ('/sys/kernel/config/nvmet/subsystems/' , subsysnqn )
99117 _mkdir (dname )
100- _echo (1 , os .path .join (dname , 'attr_allow_any_host' ))
101- return dname
118+ _echo (0 if allowed_hosts else 1 , os .path .join (dname , 'attr_allow_any_host' ))
119+
120+ # Configure all the hosts that are allowed to access this subsystem
121+ for host in allowed_hosts :
122+ hostnqn = host .get ('nqn' )
123+ hostkey = host .get ('key' )
124+ if all ([hostnqn , hostkey ]):
125+ dname = os .path .join ('/sys/kernel/config/nvmet/hosts/' , hostnqn )
126+ _mkdir (dname )
127+ _echo (hostkey , os .path .join (dname , 'dhchap_key' ))
128+ _symlink_allowed_hosts (hostnqn , subsysnqn )
102129
103130
104131def _create_namespace (subsysnqn : str , id : str , node : str ) -> str :
@@ -107,7 +134,6 @@ def _create_namespace(subsysnqn: str, id: str, node: str) -> str:
107134 _mkdir (dname )
108135 _echo (node , os .path .join (dname , 'device_path' ))
109136 _echo (1 , os .path .join (dname , 'enable' ))
110- return dname
111137
112138
113139def _args_valid (id , traddr , trsvcid , trtype , adrfam ):
@@ -215,8 +241,9 @@ def create(args):
215241 str (subsystem .get ('port' )),
216242 subsystem .get ('namespaces' ),
217243 )
244+
218245 if None not in (subsysnqn , port , namespaces ):
219- _create_subsystem (subsysnqn )
246+ _create_subsystem (subsysnqn , subsystem . get ( 'allowed_hosts' , []) )
220247 for id in namespaces :
221248 _create_namespace (subsysnqn , str (id ), dev_node )
222249 else :
@@ -235,10 +262,16 @@ def clean(args):
235262 if not args .dry_run and os .geteuid () != 0 :
236263 sys .exit (f'Permission denied. You need root privileges to run { os .path .basename (__file__ )} .' )
237264
265+ print (f'###{ Fore .GREEN } 1st) Remove the symlinks{ Style .RESET_ALL } ' )
238266 print ('rm -f /sys/kernel/config/nvmet/ports/*/subsystems/*' )
239267 for dname in pathlib .Path ('/sys/kernel/config/nvmet/ports' ).glob ('*/subsystems/*' ):
240268 _runcmd (['rm' , '-f' , str (dname )], quiet = True )
241269
270+ print ('rm -f /sys/kernel/config/nvmet/subsystems/*/allowed_hosts/*' )
271+ for dname in pathlib .Path ('/sys/kernel/config/nvmet/subsystems' ).glob ('*/allowed_hosts/*' ):
272+ _runcmd (['rm' , '-f' , str (dname )], quiet = True )
273+
274+ print (f'###{ Fore .GREEN } 2nd) Remove directories{ Style .RESET_ALL } ' )
242275 print ('rmdir /sys/kernel/config/nvmet/ports/*' )
243276 for dname in pathlib .Path ('/sys/kernel/config/nvmet/ports' ).glob ('*' ):
244277 _runcmd (['rmdir' , str (dname )], quiet = True )
@@ -251,6 +284,11 @@ def clean(args):
251284 for dname in pathlib .Path ('/sys/kernel/config/nvmet/subsystems' ).glob ('*' ):
252285 _runcmd (['rmdir' , str (dname )], quiet = True )
253286
287+ print ('rmdir /sys/kernel/config/nvmet/hosts/*' )
288+ for dname in pathlib .Path ('/sys/kernel/config/nvmet/hosts' ).glob ('*' ):
289+ _runcmd (['rmdir' , str (dname )], quiet = True )
290+
291+ print (f'###{ Fore .GREEN } 3rd) Unload kernel modules{ Style .RESET_ALL } ' )
254292 for module in _get_loaded_nvmet_modules ():
255293 _modprobe (module , ['--remove' ])
256294
0 commit comments