def init(self): """ Create and initialize Loopback. - Args : - None. - Returns : - True on success, False on failure. """ if self.dev_size == 0 or self.block_size == 0: self.logger.err("invalid device size or block size") return False count = self.dev_size / self.block_size for i in range(0, self.max_loop): file_path = self.path + "/test" + str(i) cmd = "dd if=/dev/zero of=" + file_path + \ " count=" + str(count) + " bs=" + str(self.block_size) self.logger.info(cmd) ret = Cmd.exec_cmd(cmd) if ret is False: self.logger.error("lookback file creation " + self.dev_list[i]) self.delete() return False dev = "/dev/loop" + str(i) cmd = "losetup " + dev + " " + file_path self.logger.info(cmd) if Cmd.exec_cmd(cmd) is False: self.logger.error(cmd + " failed.") return False self.dev_list.append(dev) return True
def init(self): """ Create and initialize port. - Args : - None. - Returns : - True on success, False on failure. """ if self.port_conf['addr_trtype'] != "loop": self.logger.error("only loop transport type is supported.") return False ret = Cmd.exec_cmd("mkdir -p " + self.port_path) if ret is False: self.logger.error("failed to create " + self.port_path + ".") return False # initialize transport type self.logger.info("Port " + self.port_path + " created successfully.") ret = Cmd.exec_cmd("echo -n \"" + self.port_conf['addr_trtype'] + "\" > " + self.port_path + "/addr_trtype") if ret is False: status = "trtype " + self.port_path + " failed." self.logger.error(status) else: status = "Port " + self.port_path + " initialized successfully." self.logger.info(status) return ret
def __init__(self): self.nr_devices = None self.ctrl_list = [] self.dev_list = [] self.logger = Log.get_logger(__name__, 'nvme_pci') Cmd.exec_cmd("modprobe -r nvme") Cmd.exec_cmd("modprobe nvme") # allow devices to appear in /dev/ time.sleep(1)
def delete(self): """ Delete subsystem and associated namespace(s). - Args : - None. - Returns : - True on success, False on failure. """ self.logger.info("Deleting subsystem " + self.nqn + ".") for host_ns in self.ns_list: host_ns.delete() cmd = "dirname $(grep -ls " + self.nqn + \ " /sys/class/nvme-fabrics/ctl/*/subsysnqn)" try: proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) for line in proc.stdout: line = line.strip('\n') if not os.path.isdir(line): self.logger.error("host ctrl dir " + self.nqn + " not present.") return False cmd = "nvme disconnect -n " + self.nqn self.logger.info("disconnecting : " + cmd) ret = Cmd.exec_cmd(cmd) if ret is False: self.logger.error("failed to delete ctrl " + self.nqn + ".") return False except Exception, err: self.logger.error(str(err) + ".") return False
class NVMFTargetSubsystem(object): """ Represents a target subsystem. - Attributes : - ns_list : list of namespaces. - cfgfs : configfs path. - nqn : subsystem nqn. - subsys_path : subsystem path in configfs. - allowed_hosts : configfs allowed host attribute. - attr_allow_any_host : configfs allow any host attribute. """ def __init__(self, cfgfs, nqn, allowed_hosts, attr_allow_any_host): self.ns_list = [] self.cfgfs = cfgfs self.nqn = nqn self.subsys_path = self.cfgfs + Const.SYSFS_NVMET_SUBSYS + nqn + "/" self.allowed_hosts = allowed_hosts self.attr_allow_any_host = attr_allow_any_host self.logger = Log.get_logger(__name__, 'target_subsystem') self.ns_list_index = 0 def __iter__(self): self.ns_list_index = 0 return self def __next__(self): index = self.ns_list_index self.ns_list_index += 1 if len(self.ns_list) > index: return self.ns_list[index] raise StopIteration def next(self): """ Iterator next function """ return self.__next__() def init(self): """ Create and initialize target subsystem. - Args : - None. - Returns : - True on success, False on failure. """ # create subsystem dir self.logger.info("Creating subsys path " + self.subsys_path + ".") try: os.makedirs(self.subsys_path) except Exception, err: self.logger.error(str(err) + ".") return False # allow any host self.logger.info("Configuring allowed hosts ...") ret = Cmd.exec_cmd("echo " + self.attr_allow_any_host + " >" + self.subsys_path + "/attr_allow_any_host") if ret is False: self.logger.error(self.subsys_path + " creation failed.") else: self.logger.info(self.subsys_path + " created successfully.") return ret
def is_mounted(self): """ Check if mount_path is mounted. - Args : - None. - Returns : - True on success, False on failure. """ return Cmd.exec_cmd("mountpoint -q " + self.mount_path)
def delete(self): """ Delete this Loopback. - Args : - None. -Returns : - True on success, False on failure. """ loop_cnt = 0 for i in self.dev_list: cmd = "losetup -d /dev/loop" + str(loop_cnt) self.logger.info(cmd) Cmd.exec_cmd(cmd) file_path = self.path + "/test" + str(loop_cnt) os.remove(file_path) loop_cnt += 1 return Cmd.exec_cmd("modprobe -qr loop")
def delete(self): """ Remove the nvme module. - Args : - None. -Returns : - True on success, False on failure. """ return Cmd.exec_cmd("modprobe -qr nvme")
def enable(self): """ Enable Namespace. - Args : - None. - Returns : - True on success, False on failure. """ self.ns_attr['enable'] = '1' return Cmd.exec_cmd("echo 1 > " + self.ns_path + "/enable")
def get_ns_id(self): """ Wrapper for get-ns-id command. - Args : - None. - Returns : - True on success, False on failure. """ get_ns_id_cmd = "nvme get-ns-id " + self.ns_dev return Cmd.exec_cmd(get_ns_id_cmd)
def ns_descs(self): """ Wrapper for ns-descs command. - Args : - None. - Returns : - True on success, False on failure. """ ns_descs_cmd = "nvme ns-descs " + self.ns_dev return Cmd.exec_cmd(ns_descs_cmd)
def id_ns(self): """ Wrapper for id-ns command. - Args : - None. - Returns : - True on success, False on failure. """ id_ns_cmd = "nvme id-ns " + self.ns_dev return Cmd.exec_cmd(id_ns_cmd)
def is_pci_ctrl(self, ctrl): """ Validate underlaying device belongs to pci subsystem. - Args : - None. - Returns : - True if device is belongs to PCIe subsystem, False otherwise. """ cmd = "find /sys/devices -name " + ctrl + " | grep -i pci" return Cmd.exec_cmd(cmd)
def umount(self): """ Unmount target device from mount path. - Args : - None. - Returns : - True on success, False on failure. """ if super(Ext4FS, self).umount() is False: return False ret = True Cmd.exec_cmd("umount " + self.mount_path) try: os.rmdir(self.mount_path) except Exception as err: self.logger.info(str(err)) ret = False return ret
def mount(self): """ Mount Target device on the mount path. - Args : - None. - Returns : - True on success, False on failure. """ if super(Ext4FS, self).mount() is False: return False return Cmd.exec_cmd("mount " + self.dev_path + " " + self.mount_path)
def load_modules(self): """ Wrapper for Loading NVMF Host modules. - Args : - None. - Returns : - True on success, False on failure. """ if Cmd.exec_cmd("modprobe nvme-fabrics") is False: self.logger.error("unable to load nvme-fabrics.") return False return True
def __ctrl_set_attr__(self, attr): """ Set host controller attribute. - Args : - attr : sysfs attribute to set. - Returns : - True on success, False on failure. """ sysfs_path = "/sys/class/nvme-fabrics/ctl/" cmd = "echo 1 >" + sysfs_path + self.ctrl_dev.split('/')[-1] \ + "/" + attr return Cmd.exec_cmd(cmd)
def load_configfs(self): """ Load configfs. - Args : - None. -Returns : - True on success, False on failure. """ Cmd.exec_cmd("modprobe configfs") ret = Cmd.exec_cmd("mountpoint -q " + self.cfgfs) if ret is False: ret = Cmd.exec_cmd("mount -t configfs none " + self.cfgfs) if ret is False: self.logger.error("failed to mount configfs.") sys.exit(ret) ret = Cmd.exec_cmd("mountpoint -q " + self.cfgfs) if ret is True: self.logger.info("Configfs mounted at " + self.cfgfs + ".") else: self.logger.error("unable to mount configfs at " + self.cfgfs + ".") return ret
class NVMFTargetNamespace(object): """ Represents a target namespace. - Attributes : - ns_attr : namespace attributes. - cfgfs : configfs path. - nqn : subsystem nqn. - ns_id : namespace identifier. - ns_path : namespace path in configfs tree. - ns_attr : namespace attributes. """ def __init__(self, cfgfs, nqn, ns_id, **ns_attr): self.ns_attr = {} self.cfgfs = cfgfs self.nqn = nqn self.ns_id = ns_id self.ns_path = (self.cfgfs + Const.SYSFS_NVMET_SUBSYS + nqn + Const.SYSFS_NVMET_SUBSYS_NS + str(ns_id) + "/") self.ns_attr['device_nguid'] = ns_attr['device_nguid'] self.ns_attr['device_path'] = ns_attr['device_path'] self.ns_attr['enable'] = ns_attr['enable'] self.logger = Log.get_logger(__name__, 'target_ns') def init(self): """ Create and initialize namespace. - Args : - None. - Returns : - True on success, False on failure. """ self.logger.info("Creating ns " + self.ns_path + " ...") try: os.makedirs(self.ns_path) except Exception, err: self.logger.error(str(err) + ".") return False cmd = "echo -n " + self.ns_attr['device_path'] + " > " + \ self.ns_path + "/device_path" if Cmd.exec_cmd(cmd) is False: self.logger.error("failed to configure device path.") return False if self.ns_attr['enable'] == '1': if self.enable() is False: self.logger.error("enable ns " + self.ns_path + " failed.") return False self.logger.info("NS " + self.ns_path + " enabled.") return True
def config(self, config_file="config/loop.json"): """ Wrapper for creating target configuration. - Args : - config_file : json config_file. -Returns : - True on success, False on failure. """ if Cmd.exec_cmd("modprobe nvme") is False: self.logger.error("failed to load nvme.") return False if Cmd.exec_cmd("modprobe nvmet") is False: self.logger.error("unable to load nvmet module.") return False ret = False if self.target_type == "loop": self.logger.info("Configuring loop target ... ") ret = self.config_loop_target(config_file) else: self.logger.error("only loop target type is supported.") return ret
def validate_fabric_ctrl(self): """ Validate this is a fabric controller. - Args : - None. - Returns : - True on success, False on failure. """ if not stat.S_ISCHR(os.stat(self.ctrl_dev).st_mode): self.logger.error("failed to find char device for host ctrl.") cmd = "find /sys/devices -name " + self.ctrl_dev.split("/")[-2] \ + " | grep nvme-fabric" self.logger.info(cmd) return Cmd.exec_cmd(cmd)
def add_subsys(self, subsys_name): """ Link Subsystem to this port. - Args : - subsys_name : subsystem nqn to be linked. - Returns : - True on success, False on failure. """ src = self.cfgfs + "/nvmet/subsystems/" + subsys_name if not os.path.exists(src): self.logger.error("subsystem '" + src + "' not present.") return False dest = self.port_path + "/subsystems/" cmd = "ln -s " + src + " " + dest self.logger.info(cmd) return Cmd.exec_cmd(cmd)
def mkfs(self): """ Execute mkfs on target deivce. - Args : - None. - Returns : - True on success, False on failure. """ if super(Ext4FS, self).mkfs() is False: return False if Cmd.exec_cmd("mkfs.ext4 " + self.dev_path) is False: self.logger.error("mkfs failed") return False self.logger.info("mkfs successful!!!") return True
def __init__(self, path, dev_size, block_size, max_loop): self.path = path self.dev_size = dev_size self.block_size = block_size self.max_loop = max_loop self.dev_list = [] self.logger = Log.get_logger(__name__, 'loopback') self.logger.setLevel(logging.DEBUG) Cmd.exec_cmd("losetup -D") Cmd.exec_cmd("modprobe -qr loop") Cmd.exec_cmd("modprobe loop max_loop=" + str(max_loop))
def init_ctrl(self): """ Initialize controller and build controller attributes. - Args : - None. - Returns : - True on success, False on failure. """ # initialize nqn and transport cmd = "echo \"transport=" + self.transport + ",nqn=" + \ self.nqn + "\" > /dev/nvme-fabrics" self.logger.info("Host Connect command : " + cmd) if Cmd.exec_cmd(cmd) is False: self.logger.info("ERROR : host connect command failed") return False self.ctrl_dev, self.ns_dev_list = self.build_ns_list() if self.validate_fabric_ctrl() is False or self.id_ctrl() is False: return False return self.init_ns()
def config_loop_target(self, config_file): """ Configure loop target :- 1. Create subsystem(s) and respective namespace(s). 2. Create port(s) and linked them to respective subsystem(s). 3. Create in memory configuration from JSON config file. - Args : - config_file : json config file path. -Returns : - True on success, False on failure. """ ret = Cmd.exec_cmd("modprobe nvme-loop") if ret is False: self.logger.error("failed to load nvme-loop.") return False try: config_file_handle = open(config_file, "r") config = json.loads(config_file_handle.read()) config_file_handle.close() except Exception, err: self.logger.error(str(err) + ".") return False
def delete(self): """ Target Cleanup. - Args : - None. -Returns : - True on success, False on failure. """ self.logger.info("Cleanup is in progress ...") ret = True for port in self.port_list: if port.delete() is False: ret = False for subsys in iter(self): if subsys.delete() is False: ret = False self.logger.info("Removing Modules ...") Cmd.exec_cmd("modprobe -r nvme_loop") Cmd.exec_cmd("modprobe -r nvmet") Cmd.exec_cmd("modprobe -r nvme_fabrics") self.logger.info("DONE.") return ret