def access_group_init_add(req, ag_name, init_id, init_type): if init_type != 'iscsi': raise TargetdError(TargetdError.NO_SUPPORT, "Only support iscsi") tpg = _get_iscsi_tpg() # Pre-check: # 1. Already in requested access group, return silently. # 2. Initiator does not exist. # 3. Initiator not used by other access group. if init_id in list(NodeACLGroup(tpg, ag_name).wwns): return for node_acl_group in tpg.node_acl_groups: if init_id in list(node_acl_group.wwns): raise TargetdError( TargetdError.EXISTS_INITIATOR, "Requested init_id is used by other access group") for node_acl in tpg.node_acls: if init_id == node_acl.node_wwn: raise TargetdError(TargetdError.EXISTS_INITIATOR, "Requested init_id is in use") NodeACLGroup(tpg, ag_name).add_acl(init_id) RTSRoot().save_to_file()
def refresh(self): self._children = set([]) for so in RTSRoot().storage_objects: if so.plugin == 'user': idx = so.config.find("/") handler = so.config[:idx] if handler == self.handler: ui_so = self.so_cls(so, self)
def __init__(self): self.block_store = {} self.target = {} self.root = RTSRoot() self.iscsi = FabricModule('iscsi') self.mapped_luns = {} self.get_block_store_objects() self.get_targets()
def access_group_init_del(req, ag_name, init_id, init_type): if init_type != 'iscsi': raise TargetdError(TargetdError.NO_SUPPORT, "Only support iscsi") tpg = _get_iscsi_tpg() # Pre-check: # 1. Initiator is not in requested access group, return silently. if init_id not in list(NodeACLGroup(tpg, ag_name).wwns): return NodeACLGroup(tpg, ag_name).remove_acl(init_id) RTSRoot().save_to_file()
def access_group_map_destroy(req, pool_name, vol_name, ag_name): tpg = _get_iscsi_tpg() node_acl_group = NodeACLGroup(tpg, ag_name) tpg_lun = _tpg_lun_of(tpg, pool_name, vol_name) for map_group in node_acl_group.mapped_lun_groups: if map_group.tpg_lun == tpg_lun: map_group.delete() if not any(tpg_lun.mapped_luns): # If LUN is not masked to any access group or initiator # remove LUN instance. lun_so = tpg_lun.storage_object tpg_lun.delete() lun_so.delete() RTSRoot().save_to_file()
def export_create(req, pool, vol, initiator_wwn, lun): fm = FabricModule('iscsi') t = Target(fm, target_name) tpg = TPG(t, 1) tpg.enable = True tpg.set_attribute("authentication", '0') NetworkPortal(tpg, "0.0.0.0") na = NodeACL(tpg, initiator_wwn) tpg_lun = _tpg_lun_of(tpg, pool, vol) # only add mapped lun if it doesn't exist for tmp_mlun in tpg_lun.mapped_luns: if tmp_mlun.mapped_lun == lun and tmp_mlun.parent_nodeacl == na: break else: MappedLUN(na, lun, tpg_lun) RTSRoot().save_to_file()
def access_group_map_create(req, pool_name, vol_name, ag_name, h_lun_id=None): tpg = _get_iscsi_tpg() tpg.enable = True tpg.set_attribute("authentication", '0') set_portal_addresses(tpg) tpg_lun = _tpg_lun_of(tpg, pool_name, vol_name) # Pre-Check: # 1. Already mapped to requested access group, return None if any(tpg_lun.mapped_luns): tgt_map_list = access_group_map_list(req) for tgt_map in tgt_map_list: if tgt_map['ag_name'] == ag_name and \ tgt_map['pool_name'] == pool_name and \ tgt_map['vol_name'] == vol_name: # Already masked. return None node_acl_group = NodeACLGroup(tpg, ag_name) if not any(node_acl_group.wwns): # Non-existent access group means volume mapping status will not be # stored. This should be considered as an error instead of silently # returning. raise TargetdError(TargetdError.NOT_FOUND_ACCESS_GROUP, "Access group not found") if h_lun_id is None: # Find out next available host LUN ID # Assuming max host LUN ID is MAX_LUN free_h_lun_ids = set(range(MAX_LUN + 1)) - \ set([int(x.mapped_lun) for x in tpg_lun.mapped_luns]) if len(free_h_lun_ids) == 0: raise TargetdError(TargetdError.NO_FREE_HOST_LUN_ID, "All host LUN ID 0 ~ %d is in use" % MAX_LUN) else: h_lun_id = free_h_lun_ids.pop() node_acl_group.mapped_lun_group(h_lun_id, tpg_lun) RTSRoot().save_to_file()
def initiator_set_auth(req, initiator_wwn, in_user, in_pass, out_user, out_pass): fm = FabricModule('iscsi') t = Target(fm, target_name) tpg = TPG(t, 1) na = NodeACL(tpg, initiator_wwn) if not in_user or not in_pass: # rtslib treats '' as its NULL value for these in_user = in_pass = '' if not out_user or not out_pass: out_user = out_pass = '' na.chap_userid = in_user na.chap_password = in_pass na.chap_mutual_userid = out_user na.chap_mutual_password = out_pass RTSRoot().save_to_file()
def export_destroy(req, pool, vol, initiator_wwn): mod = pool_module(pool) fm = FabricModule('iscsi') t = Target(fm, target_name) tpg = TPG(t, 1) na = NodeACL(tpg, initiator_wwn) pool_dev_name = mod.pool2dev_name(pool) for mlun in na.mapped_luns: # all SOs are Block so we can access udev_path safely if mod.has_udev_path(mlun.tpg_lun.storage_object.udev_path): mlun_vg, mlun_name = \ mod.split_udev_path(mlun.tpg_lun.storage_object.udev_path) if mlun_vg == pool_dev_name and mlun_name == vol: tpg_lun = mlun.tpg_lun mlun.delete() # be tidy and delete unused tpg lun mappings? if not any(tpg_lun.mapped_luns): so = tpg_lun.storage_object tpg_lun.delete() so.delete() break else: raise TargetdError(TargetdError.NOT_FOUND_VOLUME_EXPORT, "Volume '%s' not found in %s exports" % (vol, initiator_wwn)) # Clean up tree if branch has no leaf if not any(na.mapped_luns): na.delete() if not any(tpg.node_acls): tpg.delete() if not any(t.tpgs): t.delete() RTSRoot().save_to_file()
def access_group_create(req, ag_name, init_id, init_type): if init_type != 'iscsi': raise TargetdError(TargetdError.NO_SUPPORT, "Only support iscsi") name_check(ag_name) tpg = _get_iscsi_tpg() # Pre-check: # 1. Name conflict: requested name is in use # 2. Initiator conflict: request initiator is in use for node_acl_group in tpg.node_acl_groups: if node_acl_group.name == ag_name: raise TargetdError(TargetdError.NAME_CONFLICT, "Requested access group name is in use") if init_id in list(i.node_wwn for i in tpg.node_acls): raise TargetdError(TargetdError.EXISTS_INITIATOR, "Requested init_id is in use") node_acl_group = NodeACLGroup(tpg, ag_name) node_acl_group.add_acl(init_id) RTSRoot().save_to_file()
def export_destroy(req, pool, vol, initiator_wwn): pool_check(pool) fm = FabricModule('iscsi') t = Target(fm, target_name) tpg = TPG(t, 1) na = NodeACL(tpg, initiator_wwn) vg_name, thin_pool = get_vg_lv(pool) for mlun in na.mapped_luns: # all SOs are Block so we can access udev_path safely mlun_vg, mlun_name = \ mlun.tpg_lun.storage_object.udev_path.split("/")[2:] if mlun_vg == vg_name and mlun_name == vol: tpg_lun = mlun.tpg_lun mlun.delete() # be tidy and delete unused tpg lun mappings? if not any(tpg_lun.mapped_luns): so = tpg_lun.storage_object tpg_lun.delete() so.delete() break else: raise TargetdError( -151, "Volume '%s' not found in %s exports" % (vol, initiator_wwn)) # Clean up tree if branch has no leaf if not any(na.mapped_luns): na.delete() if not any(tpg.node_acls): tpg.delete() if not any(t.tpgs): t.delete() RTSRoot().save_to_file()
def __init__(self, shell, as_root=False): UINode.__init__(self, '/', shell=shell) self.as_root = as_root self.rtsroot = RTSRoot()
def access_group_destroy(req, ag_name): NodeACLGroup(_get_iscsi_tpg(), ag_name).delete() RTSRoot().save_to_file()
def ui_command_create(self, name, file_or_dev, size=None, write_back=None, sparse=None, wwn=None): ''' Creates a FileIO storage object. If I{file_or_dev} is a path to a regular file to be used as backend, then the I{size} parameter is mandatory. Else, if I{file_or_dev} is a path to a block device, the size parameter B{must} be ommited. If present, I{size} is the size of the file to be used, I{file} the path to the file or I{dev} the path to a block device. The I{write_back} parameter is a boolean controlling write caching. It is enabled by default. The I{sparse} parameter is only applicable when creating a new backing file. It is a boolean stating if the created file should be created as a sparse file (the default), or fully initialized. SIZE SYNTAX =========== - If size is an int, it represents a number of bytes. - If size is a string, the following units can be used: - B{B} or no unit present for bytes - B{k}, B{K}, B{kB}, B{KB} for kB (kilobytes) - B{m}, B{M}, B{mB}, B{MB} for MB (megabytes) - B{g}, B{G}, B{gB}, B{GB} for GB (gigabytes) - B{t}, B{T}, B{tB}, B{TB} for TB (terabytes) ''' self.assert_root() sparse = self.ui_eval_param(sparse, 'bool', True) write_back = self.ui_eval_param(write_back, 'bool', True) wwn = self.ui_eval_param(wwn, 'string', None) self.shell.log.debug("Using params size=%s write_back=%s sparse=%s" % (size, write_back, sparse)) file_or_dev = os.path.expanduser(file_or_dev) # can't use is_dev_in_use() on files so just check against other # storage object paths if os.path.exists(file_or_dev): for so in RTSRoot().storage_objects: if so.udev_path and os.path.samefile(file_or_dev, so.udev_path): raise ExecutionError("storage object for %s already exists: %s" % \ (file_or_dev, so.name)) if get_block_type(file_or_dev) is not None: if size: self.shell.log.info("Block device, size parameter ignored") size = None self.shell.log.info( "Note: block backstore preferred for best results") else: # use given file size only if backing file does not exist if os.path.isfile(file_or_dev): new_size = os.path.getsize(file_or_dev) if size: self.shell.log.info( "%s exists, using its size (%s bytes) instead" % (file_or_dev, new_size)) size = new_size elif os.path.exists(file_or_dev): raise ExecutionError("Path %s exists but is not a file" % file_or_dev) else: # create file and extend to given file size if not size: raise ExecutionError("Attempting to create file for new" + " fileio backstore, need a size") size = human_to_bytes(size) self._create_file(file_or_dev, size, sparse) so = FileIOStorageObject(name, file_or_dev, size, write_back=write_back, wwn=wwn) ui_so = UIFileioStorageObject(so, self) self.setup_model_alias(so) self.shell.log.info("Created fileio %s with size %s" % (name, so.size)) return self.new_node(ui_so)
def refresh(self): self._children = set([]) for so in RTSRoot().storage_objects: if so.plugin == self.name: ui_so = self.so_cls(so, self)