summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormnc <mnc@d7303112-9cec-0310-bdd2-e83a94d6c2b6>2006-11-08 17:58:56 +0000
committermnc <mnc@d7303112-9cec-0310-bdd2-e83a94d6c2b6>2006-11-08 17:58:56 +0000
commit95e2e89a23e7c85cebdd97ca373bf0cffcafeca3 (patch)
tree7c246191cd239bf18a68312f03e776d5efbc298f
parent0cabf50bbf127f374ebaf6a9b9770e527dd7888e (diff)
downloadopen-iscsi-95e2e89a23e7c85cebdd97ca373bf0cffcafeca3.tar.gz
add login/logout all commands
git-svn-id: svn://svn.berlios.de/open-iscsi@722 d7303112-9cec-0310-bdd2-e83a94d6c2b6
-rw-r--r--README8
-rw-r--r--doc/iscsiadm.819
-rw-r--r--usr/config.h1
-rw-r--r--usr/idbm.c7
-rw-r--r--usr/idbm.h3
-rw-r--r--usr/iscsiadm.c192
6 files changed, 218 insertions, 12 deletions
diff --git a/README b/README
index ff392f1..e17ad2c 100644
--- a/README
+++ b/README
@@ -186,6 +186,14 @@ Usage: iscsiadm [OPTION]
[new], [delete], [update] or [show]. In case of
[update], you have to provide [name] and [value]
you wish to update
+ -m node --logoutall=[all,manual,automatic]
+ Logout "all" the running sessions or just the ones
+ with startup value manial or automatic.
+ Nodes marked as ONBOOT are skipped.
+ -m node --loginall=[all,manual,automatic]
+ Login "all" the running sessions or just the ones
+ with startup value manial or automatic.
+ Nodes marked as ONBOOT are skipped.
-m session display all active sessions and connections
-m session --sid=[sid] [--logout]
perform operation for specific session with
diff --git a/doc/iscsiadm.8 b/doc/iscsiadm.8
index 3a200a7..6368d0d 100644
--- a/doc/iscsiadm.8
+++ b/doc/iscsiadm.8
@@ -5,7 +5,7 @@ iscsiadm \- open-iscsi administration utility
\fBiscsiadm\fR -m discovery [ -dhV ] [ -t type -p ip:port [ -l ] ] |
[ -o operation ] [ -n name ] [ -v value ]
-\fBiscsiadm\fR -m node [ -dhV ] [ -S ] [ [ -T targetname -p ip:port | -M sysdir ] [ -l | -u ] ]
+\fBiscsiadm\fR -m node [ -dhV ] [ -L all,manual,automatic ] [ -U all,manual,automatic ] [ -S ] [ [ -T targetname -p ip:port | -M sysdir ] [ -l | -u ] ]
[ [ -o operation ] [ -n name ] [ -v value ] [ -p ip:port ] ]
\fBiscsiadm\fR -m session [ -dhV ] [ -r sessionid [ -u | -s ] ]
@@ -36,6 +36,15 @@ all discovered targets.
This option is only valid for discovery and node modes.
.TP
+\fB\-L\fR, \fB\-\-loginall==\fI[all,manual,automatic]\fR
+For node mode, login all sessions with the node.startup values passed in
+or all running sesssion, except ones marked onboot, if all is passed in.
+.IP
+This option is only valid for node mode (it is valid but not functional
+for session mode).
+
+
+.TP
\fB\-m, \-\-mode \fIop\fR
specify the mode. \fIop\fR
must be one of \fIdiscovery\fR, \fInode\fR, or \fIsession\fR.
@@ -126,6 +135,14 @@ This option is only valid for node mode (it is valid but not functional
for session mode).
.TP
+\fB\-U\fR, \fB\-\-logoutall==\fI[all,manual,automatic]\fR
+logout all sessions with the node.startup values passed in or all
+running sesssion, except ones marked onboot, if all is passed in.
+.IP
+This option is only valid for node mode (it is valid but not functional
+for session mode).
+
+.TP
\fB\-v\fR, \fB\-\-value=\fIvalue\fR
Specify a \fIvalue\fR for use with the \fIupdate\fR operator.
.IP
diff --git a/usr/config.h b/usr/config.h
index 35deed8..7d00238 100644
--- a/usr/config.h
+++ b/usr/config.h
@@ -160,6 +160,7 @@ struct iscsi_slp_config {
typedef enum iscsi_startup {
ISCSI_STARTUP_MANUAL,
ISCSI_STARTUP_AUTOMATIC,
+ ISCSI_STARTUP_ONBOOT,
} iscsi_startup_e;
typedef enum discovery_type {
diff --git a/usr/idbm.c b/usr/idbm.c
index e290b66..8c5f980 100644
--- a/usr/idbm.c
+++ b/usr/idbm.c
@@ -646,7 +646,8 @@ int idbm_print_all_discovery(idbm_t *db)
return found;
}
-int idbm_print_nodes(idbm_t *db)
+int idbm_for_each_node(idbm_t *db, void *data,
+ int (* fn)(void *data, node_rec_t *rec))
{
DIR *node_dirfd, *portal_dirfd;
struct dirent *node_dent, *portal_dent;
@@ -689,9 +690,7 @@ int idbm_print_nodes(idbm_t *db)
tmp_ip, tmp_port))
continue;
- printf("%s:%d,%d %s\n",
- rec.conn[0].address, rec.conn[0].port,
- rec.tpgt, rec.name);
+ fn(data, &rec);
found++;
}
closedir(portal_dirfd);
diff --git a/usr/idbm.h b/usr/idbm.h
index eff7a36..d6c05f6 100644
--- a/usr/idbm.h
+++ b/usr/idbm.h
@@ -64,7 +64,8 @@ extern char* get_iscsi_initiatoralias(char *pathname);
extern idbm_t* idbm_init(char *configfile);
extern void idbm_terminate(idbm_t *db);
extern int idbm_print_node(idbm_t *db, node_rec_t *rec, int show);
-extern int idbm_print_nodes(idbm_t *db);
+extern int idbm_for_each_node(idbm_t *db, void *data,
+ int (* fn)(void *data, node_rec_t *rec));
extern int idbm_print_discovery(idbm_t *db, discovery_rec_t *rec, int show);
extern int idbm_print_all_discovery(idbm_t *db);
extern int idbm_delete_discovery(idbm_t *db, discovery_rec_t *rec);
diff --git a/usr/iscsiadm.c b/usr/iscsiadm.c
index 8ad40e7..b482359 100644
--- a/usr/iscsiadm.c
+++ b/usr/iscsiadm.c
@@ -74,7 +74,9 @@ static struct option const long_options[] =
{"value", required_argument, NULL, 'v'},
{"sid", required_argument, NULL, 'r'},
{"login", no_argument, NULL, 'l'},
+ {"loginall", required_argument, NULL, 'L'},
{"logout", no_argument, NULL, 'u'},
+ {"logoutall", required_argument, NULL, 'U'},
{"stats", no_argument, NULL, 's'},
{"debug", required_argument, NULL, 'g'},
{"map", required_argument, NULL, 'M'},
@@ -83,7 +85,7 @@ static struct option const long_options[] =
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0},
};
-static char *short_options = "lVhm:M:p:T:d:r:n:v:o:sSt:u";
+static char *short_options = "lVhm:M:p:T:U:L:d:r:n:v:o:sSt:u";
static void usage(int status)
{
@@ -94,7 +96,7 @@ static void usage(int status)
printf("\
iscsiadm -m discovery [ -dhV ] [ -t type -p ip:port [ -l ] ] | [ -p ip:port ] \
[ -o operation ] [ -n name ] [ -v value ]\n\
-iscsiadm -m node [ -dhV ] [ -S ] [ [ -T targetname -p ip:port | -M sysdir ] [ -l | -u ] ] \
+iscsiadm -m node [ -dhV ] [ -L all,manual,automatic ] [ -U all,manual,automatic ] [ -S ] [ [ -T targetname -p ip:port | -M sysdir ] [ -l | -u ] ] \
[ [ -o operation ] [ -n name ] [ -v value ] [ -p ip:port ] ]\n\
iscsiadm -m session [ -dhV ] [ -r sessionid [ -u | -s ] ]\n");
}
@@ -288,6 +290,164 @@ session_logout(node_rec_t *rec)
}
static int
+match_startup_mode(node_rec_t *rec, char *mode)
+{
+ /*
+ * we always skip onboot because this should be handled by
+ * something else
+ */
+ if (rec->startup == ISCSI_STARTUP_ONBOOT)
+ return -1;
+
+ if ((!strcmp(mode, "automatic") &&
+ rec->startup == ISCSI_STARTUP_AUTOMATIC) ||
+ (!strcmp(mode, "manual") &&
+ rec->startup == ISCSI_STARTUP_MANUAL) ||
+ !strcmp(mode, "all"))
+ return 0;
+
+ /* support conn or session startup params */
+ if ((!strcmp(mode, "automatic") &&
+ rec->conn[0].startup == ISCSI_STARTUP_AUTOMATIC) ||
+ (!strcmp(mode, "manual") &&
+ rec->conn[0].startup == ISCSI_STARTUP_MANUAL) ||
+ !strcmp(mode, "all"))
+ return 0;
+
+ return -1;
+}
+
+struct session_mgmt_fn {
+ idbm_t *db;
+ char *mode;
+};
+
+static int
+__group_logout(void *data, char *targetname, int tpgt, char *address,
+ int port, int sid)
+{
+ struct session_mgmt_fn *mgmt = data;
+ char *mode = mgmt->mode;
+ idbm_t *db = mgmt->db;
+ node_rec_t rec;
+ int rc = 0;
+
+ log_debug(7, "logout all [%d][%s,%s.%d]\n", sid, targetname,
+ address, port);
+
+ /* for now skip qlogic and other HW and offload drivers */
+ if (!get_transport_by_sid(sid))
+ return 0;
+
+ if (idbm_node_read(db, &rec, targetname, address, port)) {
+ /*
+ * this is due to a HW driver or some other driver
+ * not hooked in
+ */
+ log_debug(7, "could not read data for [%s,%s.%d]\n",
+ targetname, address, port);
+ return 0;
+ }
+ /*
+ * we always skip on boot because if the user killed this on
+ * they would not be able to do anything
+ */
+ if (rec.startup == ISCSI_STARTUP_ONBOOT)
+ return 0;
+
+ if (!match_startup_mode(&rec, mode)) {
+ rc = session_logout(&rec);
+ /* we raced with another app or instance of iscsiadm */
+ if (rc == MGMT_IPC_ERR_NOT_FOUND)
+ rc = 0;
+ if (rc > 0) {
+ iscsid_handle_error(rc);
+ /* continue trying to logout the rest of them */
+ rc = 0;
+ }
+ }
+
+ return rc;
+}
+
+static int
+group_logout(idbm_t *db, char *mode)
+{
+ int num_found;
+ struct session_mgmt_fn mgmt;
+
+ if (!mode || !(!strcmp(mode, "automatic") || !strcmp(mode, "all") ||
+ !strcmp(mode,"manual"))) {
+ log_error("Invalid logoutall option %s.", mode);
+ usage(0);
+ return -EINVAL;
+ }
+
+ mgmt.mode = mode;
+ mgmt.db = db;
+
+ return sysfs_for_each_session(&mgmt, &num_found, __group_logout);
+}
+
+static int
+__group_login(void *data, node_rec_t *rec)
+{
+ struct session_mgmt_fn *mgmt = data;
+ char *mode = mgmt->mode;
+ int rc;
+
+ log_debug(7, "group login %s:%d,%d %s\n", rec->conn[0].address,
+ rec->conn[0].port, rec->tpgt, rec->name);
+ /*
+ * we always skip onboot because this should be handled by
+ * something else
+ */
+ if (rec->startup == ISCSI_STARTUP_ONBOOT)
+ return 0;
+
+ if (!match_startup_mode(rec, mode)) {
+ rc = session_login(rec);
+ /* we raced with another app or instance of iscsiadm */
+ if (rc == MGMT_IPC_ERR_EXISTS)
+ rc = 0;
+ if (rc > 0) {
+ iscsid_handle_error(rc);
+ /* continue trying to login the rest of them */
+ rc = 0;
+ }
+ }
+
+ return 0;
+}
+
+static int
+group_login(idbm_t *db, char *mode)
+{
+ struct session_mgmt_fn mgmt;
+
+ if (!mode || !(!strcmp(mode, "automatic") || !strcmp(mode, "all") ||
+ !strcmp(mode,"manual"))) {
+ log_error("Invalid loginall option %s.", mode);
+ usage(0);
+ return -EINVAL;
+ }
+
+ mgmt.mode = mode;
+ mgmt.db = db;
+
+ idbm_for_each_node(db, &mgmt, __group_login);
+ return 0;
+}
+
+static int
+print_node_info(void *data, node_rec_t *rec)
+{
+ printf("%s:%d,%d %s\n", rec->conn[0].address, rec->conn[0].port,
+ rec->tpgt, rec->name);
+ return 0;
+}
+
+static int
config_init(void)
{
int rc;
@@ -444,7 +604,7 @@ do_sendtargets(idbm_t *db, struct iscsi_sendtargets_config *cfg)
discovery_rec_t *drec;
if ((drec = idbm_new_discovery(db, cfg->address, cfg->port,
DISCOVERY_TYPE_SENDTARGETS, info.buffer))) {
- idbm_print_nodes(db);
+ idbm_for_each_node(db, NULL, print_node_info);
free(drec);
}
}
@@ -484,9 +644,10 @@ int
main(int argc, char **argv)
{
char *ip = NULL, *name = NULL, *value = NULL, *sysfs_device = NULL;
- char *targetname = NULL;
+ char *targetname = NULL, *group_session_mgmt_mode = NULL;
int ch, longindex, mode=-1, port=-1, do_login=0;
int rc=0, sid=-1, op=-1, type=-1, do_logout=0, do_stats=0, do_show=0;
+ int do_login_all=0, do_logout_all=0;
idbm_t *db;
struct sigaction sa_old;
struct sigaction sa_new;
@@ -544,6 +705,14 @@ main(int argc, char **argv)
case 'u':
do_logout = 1;
break;
+ case 'U':
+ do_logout_all = 1;
+ group_session_mgmt_mode= optarg;
+ break;
+ case 'L':
+ do_login_all= 1;
+ group_session_mgmt_mode= optarg;
+ break;
case 's':
do_stats = 1;
break;
@@ -691,12 +860,23 @@ main(int argc, char **argv)
node_rec_t rec;
memset(&rec, 0, sizeof(node_rec_t));
- if ((rc = verify_mode_params(argc, argv, "dmMlSonvupT", 0))) {
+ if ((rc = verify_mode_params(argc, argv, "dmMlSonvupTUL", 0))) {
log_error("node mode: option '-%c' is not "
"allowed/supported", rc);
rc = -1;
goto out;
}
+
+ if (do_login_all) {
+ rc = group_login(db, group_session_mgmt_mode);
+ goto out;
+ }
+
+ if (do_logout_all) {
+ rc = group_logout(db, group_session_mgmt_mode);
+ goto out;
+ }
+
if (sysfs_device) {
if (targetname && ip) {
log_error("only one of map and "
@@ -780,7 +960,7 @@ found_node_rec:
goto out;
}
} else if (op < 0 || op == OP_SHOW) {
- if (!idbm_print_nodes(db)) {
+ if (!idbm_for_each_node(db, NULL, print_node_info)) {
log_error("no records found!");
rc = -1;
goto out;