From 741343ad00b449cd90635a8400a2c9b045ff8be1 Mon Sep 17 00:00:00 2001 From: Alexander Eremin Date: Tue, 24 Mar 2015 04:16:55 -0700 Subject: [PATCH] 5700 add zlogin -d option to allow graceful disconnect when zone is halted Reviewed by: Andrew Gabriel Reviewed by: Jerry Jelinek Approved by: Dan McDonald --- usr/src/cmd/zlogin/zlogin.c | 20 +++++++++++++++----- usr/src/cmd/zoneadmd/zcons.c | 44 ++++++++++++++++++++++++++++++++++---------- usr/src/man/man1/zlogin.1 | 15 +++++++++++++-- 3 files changed, 62 insertions(+), 17 deletions(-) diff --git a/usr/src/cmd/zlogin/zlogin.c b/usr/src/cmd/zlogin/zlogin.c index 227e5dffcb..296c32be01 100644 --- a/usr/src/cmd/zlogin/zlogin.c +++ b/usr/src/cmd/zlogin/zlogin.c @@ -22,7 +22,7 @@ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2013 DEY Storage Systems, Inc. * Copyright (c) 2014 Gary Mills - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ /* @@ -104,6 +104,7 @@ static priv_set_t *dropprivs; static int nocmdchar = 0; static int failsafe = 0; +static int disconnect = 0; static char cmdchar = '~'; static int quiet = 0; @@ -152,7 +153,7 @@ static boolean_t forced_login = B_FALSE; static void usage(void) { - (void) fprintf(stderr, gettext("usage: %s [ -nQCES ] [ -e cmdchar ] " + (void) fprintf(stderr, gettext("usage: %s [ -dnQCES ] [ -e cmdchar ] " "[-l user] zonename [command [args ...] ]\n"), pname); exit(2); } @@ -278,8 +279,8 @@ get_console_master(const char *zname) } masterfd = sockfd; - msglen = snprintf(clientid, sizeof (clientid), "IDENT %lu %s\n", - getpid(), setlocale(LC_MESSAGES, NULL)); + msglen = snprintf(clientid, sizeof (clientid), "IDENT %lu %s %d\n", + getpid(), setlocale(LC_MESSAGES, NULL), disconnect); if (msglen >= sizeof (clientid) || msglen < 0) { zerror("protocol error"); @@ -1753,7 +1754,7 @@ main(int argc, char **argv) (void) getpname(argv[0]); username = get_username(); - while ((arg = getopt(argc, argv, "nECR:Se:l:Q")) != EOF) { + while ((arg = getopt(argc, argv, "dnECR:Se:l:Q")) != EOF) { switch (arg) { case 'C': console = 1; @@ -1779,6 +1780,9 @@ main(int argc, char **argv) case 'S': failsafe = 1; break; + case 'd': + disconnect = 1; + break; case 'e': set_cmdchar(optarg); break; @@ -1827,6 +1831,12 @@ main(int argc, char **argv) usage(); } + if (!console && disconnect != 0) { + zerror(gettext( + "-d may only be specified with console login")); + usage(); + } + if (optind == (argc - 1)) { /* * zone name, no process name; this should be an interactive diff --git a/usr/src/cmd/zoneadmd/zcons.c b/usr/src/cmd/zoneadmd/zcons.c index 963bfd3100..1466217587 100644 --- a/usr/src/cmd/zoneadmd/zcons.c +++ b/usr/src/cmd/zoneadmd/zcons.c @@ -23,6 +23,7 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright 2012 Joyent, Inc. All rights reserved. + * Copyright 2015 Nexenta Systems, Inc. All rights reserved. */ /* @@ -509,7 +510,8 @@ destroy_console_sock(int servfd) * the ident string from a client without saving it. */ static int -get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len) +get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len, + int *disconnect) { char buf[BUFSIZ], *bufp; size_t buflen = sizeof (buf); @@ -549,7 +551,8 @@ get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len) } /* - * Parse buffer for message of the form: IDENT + * Parse buffer for message of the form: + * IDENT */ bufp = buf; if (strncmp(bufp, "IDENT ", 6) != 0) @@ -562,13 +565,17 @@ get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len) while (*bufp != '\0' && isspace(*bufp)) bufp++; + buflen = strlen(bufp) - 1; + *disconnect = atoi(&bufp[buflen]); + bufp[buflen - 1] = '\0'; (void) strlcpy(locale, bufp, locale_len); return (0); } static int -accept_client(int servfd, pid_t *pid, char *locale, size_t locale_len) +accept_client(int servfd, pid_t *pid, char *locale, size_t locale_len, + int *disconnect) { int connfd; struct sockaddr_un cliaddr; @@ -578,7 +585,8 @@ accept_client(int servfd, pid_t *pid, char *locale, size_t locale_len) connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen); if (connfd == -1) return (-1); - if (get_client_ident(connfd, pid, locale, locale_len) == -1) { + if (get_client_ident(connfd, pid, locale, locale_len, + disconnect) == -1) { (void) shutdown(connfd, SHUT_RDWR); (void) close(connfd); return (-1); @@ -601,7 +609,7 @@ reject_client(int servfd, pid_t clientpid) /* * After hear its ident string, tell client to get lost. */ - if (get_client_ident(connfd, NULL, NULL, 0) == 0) { + if (get_client_ident(connfd, NULL, NULL, 0, NULL) == 0) { (void) snprintf(nak, sizeof (nak), "%lu\n", clientpid); (void) write(connfd, nak, strlen(nak)); @@ -611,7 +619,7 @@ reject_client(int servfd, pid_t clientpid) } static void -event_message(int clifd, char *clilocale, zone_evt_t evt) +event_message(int clifd, char *clilocale, zone_evt_t evt, int dflag) { char *str, *lstr = NULL; char lmsg[BUFSIZ]; @@ -635,7 +643,10 @@ event_message(int clifd, char *clilocale, zone_evt_t evt) str = "NOTICE: Zone readied"; break; case Z_EVT_ZONE_HALTED: - str = "NOTICE: Zone halted"; + if (dflag) + str = "NOTICE: Zone halted. Disconnecting..."; + else + str = "NOTICE: Zone halted"; break; case Z_EVT_ZONE_REBOOTING: if (*boot_args == '\0') { @@ -651,7 +662,10 @@ event_message(int clifd, char *clilocale, zone_evt_t evt) str = "NOTICE: Zone is being uninstalled. Disconnecting..."; break; case Z_EVT_ZONE_BOOTFAILED: - str = "NOTICE: Zone boot failed"; + if (dflag) + str = "NOTICE: Zone boot failed. Disconnecting..."; + else + str = "NOTICE: Zone boot failed"; break; case Z_EVT_ZONE_BADARGS: /*LINTED*/ @@ -708,6 +722,7 @@ do_console_io(zlog_t *zlogp, int consfd, int servfd) int pollerr = 0; char clilocale[MAXPATHLEN]; pid_t clipid = 0; + int disconnect = 0; /* console side, watch for read events */ pollfds[0].fd = consfd; @@ -801,7 +816,8 @@ do_console_io(zlog_t *zlogp, int consfd, int servfd) } else if ((clifd = accept_client(servfd, &clipid, - clilocale, sizeof (clilocale))) != -1) { + clilocale, sizeof (clilocale), + &disconnect)) != -1) { pollfds[1].fd = clifd; } else { @@ -827,7 +843,7 @@ do_console_io(zlog_t *zlogp, int consfd, int servfd) if (clifd == -1) { break; } - event_message(clifd, clilocale, evt); + event_message(clifd, clilocale, evt, disconnect); /* * Special handling for the message that the zone is * uninstalling; we boot the client, then break out @@ -838,6 +854,14 @@ do_console_io(zlog_t *zlogp, int consfd, int servfd) if (evt == Z_EVT_ZONE_UNINSTALLING) { break; } + /* + * Diconnect if -C and -d options were specified and + * zone was halted or failed to boot. + */ + if ((evt == Z_EVT_ZONE_HALTED || + evt == Z_EVT_ZONE_BOOTFAILED) && disconnect) { + break; + } } } diff --git a/usr/src/man/man1/zlogin.1 b/usr/src/man/man1/zlogin.1 index 2da43d568c..7c99eb6cb1 100644 --- a/usr/src/man/man1/zlogin.1 +++ b/usr/src/man/man1/zlogin.1 @@ -13,13 +13,14 @@ .\" Portions Copyright [yyyy] [name of copyright owner] .\" Copyright 2013 DEY Storage Systems, Inc. .\" Copyright (c) 2014 Gary Mills -.TH ZLOGIN 1 "Jan 22, 2014" +.\" Copyright 2015 Nexenta Systems, Inc. All rights reserved. +.TH ZLOGIN 1 "Mar 17, 2015" .SH NAME zlogin \- enter a zone .SH SYNOPSIS .LP .nf -\fBzlogin\fR [\fB-CEQ\fR] [\fB-e\fR \fIc\fR] [\fB-l\fR \fIusername\fR] \fIzonename\fR +\fBzlogin\fR [\fB-dCEQ\fR] [\fB-e\fR \fIc\fR] [\fB-l\fR \fIusername\fR] \fIzonename\fR .fi .LP @@ -95,6 +96,16 @@ Connects to the zone console. .sp .ne 2 .na +\fB\fB-d\fR\fR +.ad +.RS 15n +Disconnect from the console when the zone halts. This option may only be used +if the \fB-C\fR option is specified. +.RE + +.sp +.ne 2 +.na \fB\fB-e\fR \fIc\fR\fR .ad .RS 15n -- 2.11.4.GIT