Print this page
5700 add zlogin -d option to allow graceful disconnect when zone is halted
Reviewed by: Andrew Gabriel <illumos@cucumber.demon.co.uk>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
@@ -21,10 +21,11 @@
/*
* 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.
*/
/*
* Console support for zones requires a significant infrastructure. The
* core pieces are contained in this file, but other portions of note
@@ -507,11 +508,12 @@
* Read the "ident" string from the client's descriptor; this routine also
* tolerates being called with pid=NULL, for times when you want to "eat"
* 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);
char c = '\0';
int i = 0, r;
@@ -547,11 +549,12 @@
if (c == '\n')
break;
}
/*
- * Parse buffer for message of the form: IDENT <pid> <locale>
+ * Parse buffer for message of the form:
+ * IDENT <pid> <locale> <disconnect flag>
*/
bufp = buf;
if (strncmp(bufp, "IDENT ", 6) != 0)
return (-1);
bufp += 6;
@@ -560,27 +563,32 @@
if (errno != 0)
return (-1);
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;
socklen_t clilen;
clilen = sizeof (cliaddr);
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);
}
(void) write(connfd, "OK\n", 3);
@@ -599,21 +607,21 @@
connfd = accept(servfd, (struct sockaddr *)&cliaddr, &clilen);
/*
* 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));
}
(void) shutdown(connfd, SHUT_RDWR);
(void) close(connfd);
}
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];
char outbuf[BUFSIZ];
@@ -633,10 +641,13 @@
break;
case Z_EVT_ZONE_READIED:
str = "NOTICE: Zone readied";
break;
case Z_EVT_ZONE_HALTED:
+ if (dflag)
+ str = "NOTICE: Zone halted. Disconnecting...";
+ else
str = "NOTICE: Zone halted";
break;
case Z_EVT_ZONE_REBOOTING:
if (*boot_args == '\0') {
str = "NOTICE: Zone rebooting";
@@ -649,10 +660,13 @@
break;
case Z_EVT_ZONE_UNINSTALLING:
str = "NOTICE: Zone is being uninstalled. Disconnecting...";
break;
case Z_EVT_ZONE_BOOTFAILED:
+ if (dflag)
+ str = "NOTICE: Zone boot failed. Disconnecting...";
+ else
str = "NOTICE: Zone boot failed";
break;
case Z_EVT_ZONE_BADARGS:
/*LINTED*/
(void) snprintf(lmsg, sizeof (lmsg),
@@ -706,10 +720,11 @@
int cc, ret;
int clifd = -1;
int pollerr = 0;
char clilocale[MAXPATHLEN];
pid_t clipid = 0;
+ int disconnect = 0;
/* console side, watch for read events */
pollfds[0].fd = consfd;
pollfds[0].events = POLLIN | POLLRDNORM | POLLRDBAND |
POLLPRI | POLLERR | POLLHUP | POLLNVAL;
@@ -799,11 +814,12 @@
/* we're already handling a client */
reject_client(servfd, clipid);
} else if ((clifd = accept_client(servfd, &clipid,
- clilocale, sizeof (clilocale))) != -1) {
+ clilocale, sizeof (clilocale),
+ &disconnect)) != -1) {
pollfds[1].fd = clifd;
} else {
break;
}
@@ -825,11 +841,11 @@
* service lap.
*/
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
* of this function. When we return to the
* serve_console loop, we will see that the zone is
@@ -836,10 +852,18 @@
* in a state < READY, and so zoneadmd will shutdown.
*/
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;
+ }
}
}
if (clifd != -1) {