vshost-util-vserver

Build script and sources for util-vserver.
git clone https://ccx.te2000.cz/git/vshost-util-vserver
Log | Files | Refs

rebootmgr.c (6254B)


      1 // $Id$
      2 
      3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
      4 // based on rebootmgr.cc by Jacques Gelinas
      5 //  
      6 // This program is free software; you can redistribute it and/or modify
      7 // it under the terms of the GNU General Public License as published by
      8 // the Free Software Foundation; either version 2, or (at your option)
      9 // any later version.
     10 //  
     11 // This program is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 //  
     16 // You should have received a copy of the GNU General Public License
     17 // along with this program; if not, write to the Free Software
     18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     19 
     20 /*
     21 	The reboot manager allow a virtual server administrator to request
     22 	a complete restart of his vserver. This means that all services
     23 	are terminated, all remaining processes are killed and then
     24 	all services are started.
     25 
     26 	This is done by issuing
     27 
     28 		/usr/sbin/vserver vserver restart
     29 
     30 
     31 	The rebootmgr installs a unix domain socket in each vservers
     32 	and listen for the reboot messages. All other message are discarded.
     33 
     34 	The unix domain socket is placed in /vservers/N/dev/reboot and is
     35 	turned immutable.
     36 
     37 	The vreboot utility is used to send the signal from the vserver
     38 	environment.
     39 */
     40 #ifdef HAVE_CONFIG_H
     41 #  include <config.h>
     42 #endif
     43 #include "pathconfig.h"
     44 
     45 #include <stdio.h>
     46 #include <unistd.h>
     47 #include <stdlib.h>
     48 #include <sys/types.h>
     49 #include <limits.h>
     50 #include <errno.h>
     51 #include <syslog.h>
     52 #include <sys/stat.h>
     53 #include <sys/time.h>
     54 #include <sys/socket.h>
     55 #include <sys/un.h>
     56 #include <alloca.h>
     57 #include <string.h>
     58 
     59 static void usage()
     60 {
     61 	fprintf (stderr,"rebootmgr version %s\n",VERSION);
     62 	fprintf (stderr,"\n");
     63 	fprintf (stderr,"rebootmgr [--pidfile file ] vserver-name [ vserver-name ...]\n");
     64 }
     65 
     66 static int rebootmgr_opensocket (const char *vname)
     67 {
     68 	int ret = -1;
     69 	char sockn[PATH_MAX];
     70 	int fd =  socket (AF_UNIX,SOCK_STREAM,0);
     71 	sprintf (sockn, DEFAULT_VSERVERDIR "/%s/dev/reboot",vname);
     72 	unlink (sockn);
     73 	if (fd == -1){
     74 		fprintf (stderr,"Can't create a unix domain socket (%s)\n"
     75 				,strerror(errno));
     76 	}else{
     77 		struct sockaddr_un un;
     78 		un.sun_family = AF_UNIX;
     79 		strcpy (un.sun_path,sockn);
     80 		if (bind(fd,(struct sockaddr*)&un,sizeof(un))==-1){
     81 			fprintf (stderr,"Can't bind to file %s (%s)\n",sockn
     82 				,strerror(errno));
     83 		}else{
     84 		        int code;
     85 			chmod (sockn,0600);
     86 			code = listen (fd,10);
     87 			if (code == -1){
     88 				fprintf (stderr,"Can't listen to file %s (%s)\n",sockn
     89 					,strerror(errno));
     90 			}else{
     91 				ret = fd;
     92 			}	
     93 		}
     94 	}
     95 	return ret;
     96 }
     97 
     98 static int rebootmgr_process (int fd, const char *vname)
     99 {
    100 	int ret = -1;
    101 	char buf[100];
    102 	int len = read (fd,buf,sizeof(buf)-1);
    103 	// fprintf (stderr,"process %d %s len %d\n",fd,vname,len);
    104 	if (len > 0){
    105 		buf[len] = '\0';
    106 		if (strcmp(buf,"reboot\n")==0){
    107 			char cmd[1000];
    108 			syslog (LOG_NOTICE,"reboot vserver %s\n",vname);
    109 			snprintf (cmd,sizeof(cmd)-1, SBINDIR "/vserver %s restart >>/var/log/boot.log 2>&1", vname);
    110 			system (cmd);
    111 			ret = 0;
    112 		}else if (strcmp(buf,"halt\n")==0){
    113 			char cmd[1000];
    114 			syslog (LOG_NOTICE,"halt vserver %s\n",vname);
    115 			snprintf (cmd,sizeof(cmd)-1, SBINDIR "/vserver %s stop >>/var/log/boot.log 2>&1", vname);
    116 			system (cmd);
    117 			ret = 0;
    118 		}else{
    119 			syslog (LOG_ERR,"Invalid request from vserver %s",vname);
    120 		}
    121 	}
    122 	return ret;
    123 }
    124 
    125 
    126 int main (int argc, char *argv[])
    127 {
    128 	int ret = -1;
    129 	if (argc < 2){
    130 		usage();
    131 	}else{
    132 		int error = 0;
    133 		int start = 1;
    134 		int i;
    135 		int *sockets = alloca(argc * sizeof(int));
    136 
    137 		openlog ("rebootmgr",LOG_PID,LOG_DAEMON);
    138 		for (i=0; i<argc; i++){
    139 			const char *arg = argv[i];
    140 			if (strcmp(arg,"--pidfile")==0){
    141 				const char *pidfile = argv[i+1];
    142 				FILE *fout = fopen (pidfile,"w");
    143 				if (fout == NULL){
    144 					fprintf (stderr,"Can't open pidfile %s (%s)\n"
    145 						,pidfile,strerror(errno));
    146 
    147 					__extension__
    148 					syslog (LOG_ERR,"Can't open pidfile %s (%m)"
    149 						,pidfile);
    150 				}else{
    151 					fprintf (fout,"%d\n",getpid());
    152 					fclose (fout);
    153 				}
    154 				start = i+2;
    155 				i++;
    156 			}else if (strcmp(arg,"--")==0){
    157 				start = i+1;
    158 				break;
    159 			}else if (arg[0] == '-'){
    160 				fprintf (stderr,"Invalid argument %s\n",arg);
    161 				syslog (LOG_ERR,"Invalid argument %s",arg);
    162 			}
    163 		}
    164 		for (i=start; i<argc; i++){
    165 			int fd = rebootmgr_opensocket (argv[i]);
    166 			if (fd == -1){
    167 				error = 1;
    168 			}else{
    169 				sockets[i] = fd;
    170 			}
    171 		}
    172 		if (!error){
    173 			int maxhandles = argc*2;
    174 			struct {
    175 				int handle;
    176 				const char *vname;
    177 			} handles[maxhandles];
    178 			int nbhandles=0;
    179 			while (1){
    180 				int maxfd = 0;
    181 				int i;
    182 				int ok;
    183 				
    184 				fd_set fdin;
    185 				FD_ZERO (&fdin);
    186 				for (i=start; i<argc; i++){
    187 					int fd = sockets[i];
    188 					if (fd > maxfd) maxfd = fd;
    189 					FD_SET (fd,&fdin);
    190 				}
    191 				for (i=0; i<nbhandles; i++){
    192 					int fd = handles[i].handle;
    193 					if (fd > maxfd) maxfd = fd;
    194 					FD_SET (fd,&fdin);
    195 				}
    196 				ok = select (maxfd+1,&fdin,NULL,NULL,NULL);
    197 				if (ok <= 0){
    198 					break;
    199 				}else{
    200 				        int i;
    201 					int dst = 0;
    202 
    203 					for (i=start; i<argc; i++){
    204 						int fd = sockets[i];
    205 						if (FD_ISSET(fd,&fdin)){
    206 							struct sockaddr_un unc;
    207 							socklen_t len = sizeof(unc);
    208 							unc.sun_family = AF_UNIX;
    209 							fd = accept (fd,(struct sockaddr*)&unc,&len);
    210 							if (fd != -1){
    211 								if (nbhandles == maxhandles){
    212 								        int j;
    213 									// Overloaded, we close every handle
    214 									syslog (LOG_ERR,"%d sockets opened: Overloaded\n",nbhandles);
    215 									for (j=0; j<nbhandles; j++){
    216 										close (handles[j].handle);
    217 									}
    218 									nbhandles = 0;
    219 								}
    220 								handles[nbhandles].handle = fd;
    221 								handles[nbhandles].vname = argv[i];
    222 								nbhandles++;
    223 								// fprintf (stderr,"accept %d\n",nbhandles);
    224 							}
    225 						}
    226 					}
    227 					for (i=0; i<nbhandles; i++){
    228 						int fd = handles[i].handle;
    229 						if (FD_ISSET(fd,&fdin)){
    230 							if (rebootmgr_process (fd,handles[i].vname)==-1){
    231 								close (fd);
    232 							}else{
    233 								handles[dst++] = handles[i];
    234 							}
    235 						}else{
    236 							handles[dst++] = handles[i];
    237 						}
    238 					}
    239 					nbhandles = dst;
    240 				}
    241 			}
    242 		}
    243 	}
    244 	return ret;
    245 }
    246 
    247