コード例 #1
0
isns_object_t *
isns_create_storage_node2(const isns_source_t *source,
				uint32_t type,
				isns_object_t *parent)
{
	isns_attr_t	*name_attr;
	isns_object_t	*obj;

	if (parent && !ISNS_IS_ENTITY(parent)) {
		isns_warning("Invalid container type \"%s\" for storage node: "
			"should be \"%s\"\n",
			parent->ie_template->iot_name,
			isns_entity_template.iot_name);
		return NULL;
	}
	if ((name_attr = isns_source_attr(source)) == NULL) {
		isns_warning("No source attribute\n");
		return NULL;
	}

	if (name_attr->ia_tag_id == ISNS_TAG_ISCSI_NAME) {
		obj = isns_create_object(&isns_iscsi_node_template, NULL, parent);
		isns_attr_list_update_attr(&obj->ie_attrs, name_attr);
		isns_object_set_uint32(obj,
				ISNS_TAG_ISCSI_NODE_TYPE, type);
	} else {
		/* No iFCP yet, sorry */
		isns_warning("%s: source tag type %u not supported\n",
				__FUNCTION__);
		return NULL;
	}

	return obj;
}
コード例 #2
0
ファイル: scn.c プロジェクト: chris-se/open-isns
/*
 * Transmit all pending SCN messages
 *
 * 2.9.2
 * If a Network Entity has multiple Portals with registered SCN UDP Ports,
 * then SCN messages SHALL be delivered to each Portal registered to
 * receive such messages.
 *
 * FIXME: we should make this timer based just as the ESI code.
 */
time_t
isns_scn_transmit_all(void)
{
	time_t		now = time(NULL), next_timeout;
	isns_scn_t	*scn;

	for (scn = isns_scn_list; scn; scn = scn->scn_next) {
		isns_simple_t	*call;
		isns_socket_t	*sock;

		/* We do not allow more than one outstanding
		 * notification for now. */
		if ((call = scn->scn_pending) != NULL) {
			if (scn->scn_timeout > now)
				continue;
			scn->scn_current_funnel->scn_bad++;
			if (--(scn->scn_retries))
				goto retry;
			isns_warning("SCN for %s timed out\n",
					scn->scn_name);
			isns_simple_free(call);
			scn->scn_pending = NULL;
		}

		if ((call = scn->scn_message) == NULL)
			continue;

		isns_debug_scn("SCN: transmit pending message for %s\n",
				scn->scn_name);
		scn->scn_retries = isns_config.ic_scn_retries;
		scn->scn_pending = call;
		scn->scn_message = NULL;

retry:
		if ((sock = isns_scn_get_socket(scn)) == NULL) {
			/* Sorry, no can do. */
			isns_warning("SCN for %s dropped - no portal\n",
					scn->scn_name);
			scn->scn_pending = NULL;
			isns_simple_free(call);
			continue;
		}

		isns_simple_transmit(sock, call, NULL,
				isns_config.ic_scn_timeout,
				isns_process_scn_response);
		scn->scn_xid = call->is_xid;
		scn->scn_timeout = now + isns_config.ic_scn_timeout;
	}

	next_timeout = now + 3600;
	for (scn = isns_scn_list; scn; scn = scn->scn_next) {
		if (scn->scn_pending && scn->scn_timeout < next_timeout)
			next_timeout = scn->scn_timeout;
	}

	return next_timeout;
}
コード例 #3
0
ファイル: register.c プロジェクト: chris-se/open-isns
/*
 * Create a registration, and set the source name
 */
static isns_simple_t *
__isns_create_registration(isns_source_t *source, isns_object_t *key_obj)
{
	isns_simple_t	*reg;

	reg = isns_simple_create(ISNS_DEVICE_ATTRIBUTE_REGISTER, source, NULL);
	if (reg == NULL)
		return NULL;

	/*
	 * When sending a registration, you can either specify
	 * the object to be modified in the key attrs, or leave
	 * the key empty.
	 */
	if (key_obj == NULL)
		return reg;

	/* User gave us a key object. We need to put the key
	 * attributes into the message attrs, and *all* attrs
	 * into the operating attrs. */
	if (!isns_object_extract_keys(key_obj, &reg->is_message_attrs)) {
		/* bummer - seems the object is missing some
		 * vital organs. */
		isns_warning("%s: object not fully specified, key attrs missing\n",
				__FUNCTION__);
		goto failed;
	}

	/*
	 * The Message Key identifies the object the DevAttrReg message
	 * acts upon.  [...] The key attribute(s) identifying this object
	 * MUST also be included among the Operating Attributes.
	 *
	 * We do not enforce this here, we rely on the caller to get this
	 * right.
	 */
#if 0
	if (!isns_object_extract_all(key_obj, &reg->is_operating_attrs)) {
		isns_warning("%s: unable to extract attrs from key objects\n",
				__FUNCTION__);
		goto failed;
	}
#endif

	return reg;

failed:
	isns_simple_free(reg);
	return NULL;
}
コード例 #4
0
ファイル: isnsadm.c プロジェクト: Nimain/open-iscsi
int
list_objects(isns_client_t *clnt, int argc, char **argv)
{
	isns_attr_list_t	query_keys = ISNS_ATTR_LIST_INIT;
	isns_object_template_t	*query_type = NULL;
	isns_simple_t		*simp;
	int			status, count = 0;

	if (!parse_list(argc, argv, &query_type, &query_keys))
		isns_fatal("Unable to parse parameters\n");

	simp = isns_create_getnext(clnt, query_type, &query_keys);
	while (1) {
		isns_object_t	*obj = NULL;
		isns_simple_t	*followup;

		status = isns_client_call(clnt, &simp);
		if (status)
			break;

		status = isns_getnext_response_get_object(simp, &obj);
		if (status)
			break;

		printf("Object %u:\n", count++);
		isns_object_print(obj, isns_print_stdout);
		isns_object_release(obj);

		followup = isns_create_getnext_followup(clnt,
				simp, &query_keys);
		isns_simple_free(simp);
		simp = followup;
	}

	if (status == ISNS_SOURCE_UNAUTHORIZED
	 && query_type == &isns_policy_template
	 && !opt_local)
		isns_warning("Please use --local trying to list policies\n");

	if (status != ISNS_NO_SUCH_ENTRY) {
		isns_error("GetNext call failed: %s\n",
				isns_strerror(status));
		return status;
	}
	return ISNS_SUCCESS;
}
コード例 #5
0
isns_object_t *
isns_create_storage_node(const char *name, uint32_t type,
			isns_object_t *parent)
{
	isns_object_t	*obj;

	if (parent && !ISNS_IS_ENTITY(parent)) {
		isns_warning("Invalid container type \"%s\" for storage node: "
			"should be \"%s\"\n",
			parent->ie_template->iot_name,
			isns_entity_template.iot_name);
		return NULL;
	}

	obj = isns_create_object(&isns_iscsi_node_template, NULL, parent);
	isns_object_set_string(obj,
			ISNS_TAG_ISCSI_NAME, name);
	isns_object_set_uint32(obj,
			ISNS_TAG_ISCSI_NODE_TYPE, type);

	return obj;
}
コード例 #6
0
ファイル: scn.c プロジェクト: chris-se/open-isns
/*
 * This function is invoked whenever someone changes the
 * database.
 *
 * SCNs are another area where the RFC is fabulously wishy washy.
 * It is not entirely clear when DD/DDS information should be
 * included in a management SCN - one *reasonable* interpretation
 * would be that this happens for DDReg/DDDereg/DDSReg/DDSDereg
 * events only. But some sections make it sound as if DD
 * information is included for all management SCNs.
 */
void
isns_scn_callback(const isns_db_event_t *ev, void *ptr)
{
	isns_object_t	*obj = ev->ie_object;
	isns_scn_t	*scn, **pos;
	isns_attr_t	*timestamp;
	uint32_t	node_type;

	/* Never send out notifications for policy objects and the like. */
	if (obj->ie_flags & ISNS_OBJECT_PRIVATE)
		return;

	/* When an entity is nuked, remove all SCNs to nodes
	 * that registered from there */
	if (ISNS_IS_ENTITY(obj) && (ev->ie_bits & ISNS_SCN_OBJECT_REMOVED_MASK)) {
		pos = &isns_scn_list;
		while ((scn = *pos) != NULL) {
			if (scn->scn_entity != obj) {
				pos = &scn->scn_next;
				continue;
			}
			isns_debug_scn("Deleting SCN registration for %s\n",
					scn->scn_name);
			*pos = scn->scn_next;
			isns_scn_free(scn);
		}
		return;
	}

	/* For now we handle iSCSI nodes only. Maybe later we'll
	 * do iFC nodes as well. */
	if (!ISNS_IS_ISCSI_NODE(obj))
		return;
	if (!isns_object_get_uint32(obj, ISNS_TAG_ISCSI_NODE_TYPE, &node_type))
		return;

	if (ev->ie_recipient) {
		isns_object_t *dst = ev->ie_recipient;

		isns_debug_scn("SCN unicast <%s %u, %s> -> %s %u\n",
				obj->ie_template->iot_name, obj->ie_index,
				isns_event_string(ev->ie_bits),
				dst->ie_template->iot_name, dst->ie_index);
	} else {
		isns_debug_scn("SCN multicast <%s %u, %s>\n",
				obj->ie_template->iot_name, obj->ie_index,
				isns_event_string(ev->ie_bits));
	}
	timestamp = isns_create_timestamp_attr();

	pos = &isns_scn_list;
	while ((scn = *pos) != NULL) {
		unsigned int	scn_bits, management;
		isns_object_t	*recipient, *dd = NULL;
		isns_simple_t	*call;

		recipient = scn->scn_owner;

		/* Check if the node has gone away completely. */
		if (recipient->ie_scn_mask == 0) {
			*pos = scn->scn_next;
			isns_scn_free(scn);
			continue;
		}

		if (recipient->ie_container == NULL) {
			isns_warning("Internal bug - SCN recipient without container\n");
			/* Clear the bitmask and loop over - this will remove it */
			recipient->ie_scn_mask = 0;
			continue;
		}

		/* See if portals were added/removed.
		 * This does not catch updates that modified *just*
		 * the SCN port */
		if (recipient->ie_container->ie_mtime != scn->scn_last_update) {
			/* Rebuild the list of SCN portals */
			isns_scn_release_funnels(scn);
			scn->scn_last_update = 0;
		}
		pos = &scn->scn_next;

		/* Check for unicast events (triggered for DD addition/removal).
		 * For unicast events, we do not mask the SCN bits, so that
		 * clients who have registered for non-management events
		 * will see the membership events for their DDs nevertheless. */
		if (ev->ie_recipient == NULL) {
			scn_bits = ev->ie_bits & recipient->ie_scn_mask;
			if (scn_bits == 0)
				continue;
			/* Management SCNs should not be delivered to nodes
			 * that have not registered for them. */
			if ((ev->ie_bits & ISNS_SCN_MANAGEMENT_REGISTRATION_MASK)
			 && !(recipient->ie_scn_mask & ISNS_SCN_MANAGEMENT_REGISTRATION_MASK))
				continue;
		} else if (recipient == ev->ie_recipient) {
			scn_bits = ev->ie_bits;
		} else {
			/* No match, skip this recipient */
			continue;
		}

		if (scn->scn_last_update == 0) {
			scn->scn_last_update = recipient->ie_container->ie_mtime;
			isns_scn_setup(scn, recipient);
		}

		/* We check for SCN capable portals when processing
		 * the SCN registration. But the portals may go away
		 * in the meantime. */
		if (scn->scn_funnels == NULL)
			continue;

		/* Check SCN bitmask. This will modify the event bits. */
		scn_bits = isns_scn_match(scn, scn_bits, obj, node_type);
		if (scn_bits == 0)
			continue;
		management = !!(scn_bits & ISNS_SCN_MANAGEMENT_REGISTRATION_MASK);

		/*
		 * 2.2.3
		 * A regular SCN registration indicates that the
		 * Discovery Domain Service SHALL be used to control the
		 * distribution of SCN messages.  Receipt of regular
		 * SCNs is limited to the discovery domains in which
		 * the SCN-triggering event takes place.  Regular SCNs
		 * do not contain information about discovery domains.
		 *
		 * Implementer's note: We override check for unicast events.
		 * The reason is that DDDereg will sever the
		 * relationship, and we would never send an SCN for that
		 * event.
		 */
		if (!management && !ev->ie_recipient) {
			if (!isns_object_test_visibility(obj, recipient))
				continue;
		}

		isns_debug_scn("preparing to send SCN to %s\n",
				scn->scn_name);

		if ((call = scn->scn_message) == NULL) {
			call = isns_create_scn(isns_scn_server->is_source,
					scn->scn_attr,
					timestamp);
			if (call == NULL)
				continue;
			scn->scn_message = call;
		}

		/*
		 * If the SCN is a Management SCN, then the SCN message
		 * SHALL also list the DD_ID and/or DDS_ID of the
		 * Discovery Domains and Discovery Domain Sets (if any)
		 * that caused the change in state for that Storage Node.
		 * These additional attributes (i.e., DD_ID and/or DDS_ID)
		 * shall immediately follow the iSCSI Name or FC Port
		 * Name and precede the next SCN bitmap for the next
		 * notification message (if any).
		 */
		if (management && ev->ie_trigger)
			dd = ev->ie_trigger;

		isns_scn_add_event(call, scn_bits, obj, dd);

	}

	isns_attr_release(timestamp);
}