vshost-util-vserver

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

ncontext.c (8380B)


      1 // $Id$    --*- c -*--
      2 
      3 // Copyright (C) 2004-2006 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
      4 // Copyright (C) 2006 Daniel Hokka Zakrisson <daniel@hozac.com>
      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; version 2 of the License.
      9 //  
     10 // This program is distributed in the hope that it will be useful,
     11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 // GNU General Public License for more details.
     14 //  
     15 // You should have received a copy of the GNU General Public License
     16 // along with this program; if not, write to the Free Software
     17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     18 
     19 
     20 #ifdef HAVE_CONFIG_H
     21 #  include <config.h>
     22 #endif
     23 
     24 #include "util.h"
     25 #include "lib/internal.h"
     26 #include "lib_internal/util.h"
     27 #include "lib_internal/jail.h"
     28 
     29 #include <vserver.h>
     30 #include <getopt.h>
     31 #include <fcntl.h>
     32 #include <errno.h>
     33 #include <sys/socket.h>
     34 #include <sys/un.h>
     35 #include <assert.h>
     36 #include <signal.h>
     37 #include <sys/types.h>
     38 
     39 
     40 #define ENSC_WRAPPERS_PREFIX	"ncontext: "
     41 #define ENSC_WRAPPERS_UNISTD	1
     42 #define ENSC_WRAPPERS_VSERVER	1
     43 #define ENSC_WRAPPERS_FCNTL	1
     44 #define ENSC_WRAPPERS_SOCKET	1
     45 #define ENSC_WRAPPERS_IOSOCK	1
     46 #include <wrappers.h>
     47 
     48 #define CMD_HELP		0x1000
     49 #define CMD_VERSION		0x1001
     50 #define CMD_NID			0x4000
     51 #define CMD_CREATE		0x4001
     52 #define CMD_MIGRATE		0x4002
     53 #define CMD_DISCONNECT		0x4003
     54 #define CMD_SILENT		0x4004
     55 #define CMD_SYNCSOCK		0x4005
     56 #define CMD_SYNCMSG		0x4006
     57 #define CMD_MIGRATESELF		0x4007
     58 #define CMD_SILENTEXIST		0x4008
     59 
     60 
     61 struct option const
     62 CMDLINE_OPTIONS[] = {
     63   { "help",       no_argument,       0, CMD_HELP },
     64   { "version",    no_argument,       0, CMD_VERSION },
     65   { "nid",        required_argument, 0, CMD_NID },
     66   { "create",     no_argument,       0, CMD_CREATE },
     67   { "migrate",    no_argument,       0, CMD_MIGRATE },
     68   { "migrate-self", no_argument,       	0, CMD_MIGRATESELF },
     69   { "disconnect",   no_argument,	0, CMD_DISCONNECT },
     70   { "silent",       no_argument,       	0, CMD_SILENT },
     71   { "silentexist",  no_argument,       	0, CMD_SILENTEXIST },
     72   { "syncsock",     required_argument, 	0, CMD_SYNCSOCK },
     73   { "syncmsg",      required_argument, 	0, CMD_SYNCMSG },
     74   { 0,0,0,0 },
     75 };
     76 
     77 struct Arguments {
     78     bool		do_create;
     79     bool		do_migrate;
     80     bool		do_migrateself;
     81     bool		do_disconnect;
     82     bool		is_silentexist;
     83     int			verbosity;
     84     nid_t		nid;
     85     char const *	sync_sock;
     86     char const *	sync_msg;
     87 };
     88 
     89 int		wrapper_exit_code = 255;
     90 
     91 static void
     92 showHelp(int fd, char const *cmd, int res)
     93 {
     94   WRITE_MSG(fd, "Usage:\n    ");
     95   WRITE_STR(fd, cmd);
     96   WRITE_MSG(fd,
     97 	    " --create [--nid <nid>] <opts>* [--] <program> <args>*\n    ");
     98   WRITE_STR(fd, cmd);
     99   WRITE_MSG(fd,
    100 	    " [(--migrate --nid <nid>)|--migrate-self]  <opts>* [--] <program> <args>*\n"
    101 	    "\n"
    102 	    "<opts> can be:\n"
    103 	    "    --disconnect    ...  start program in background\n"
    104 	    "    --silent        ...  be silent\n"
    105 	    "    --silentexist   ...  be silent when context exists already; useful\n"
    106 	    "                         for '--create' only\n"
    107 	    "    --syncsock <filename>\n"
    108 	    "                    ...  before executing the program, send a message\n"
    109 	    "                         to the socket and wait until it closes.\n"
    110 	    "                         <filename> must be a SOCK_STREAM unix socket\n"
    111 	    "    --syncmsg <message>\n"
    112 	    "                    ...  use <message> as synchronization message; by\n"
    113 	    "                         default, 'ok' will be used\n"
    114 	    "\n"
    115 	    "'ncontext --create' exits with code 254 iff the context exists already.\n"
    116 	    "\n"
    117 	    "Please report bugs to " PACKAGE_BUGREPORT "\n");
    118 
    119   exit(res);
    120 }
    121 
    122 static void
    123 showVersion()
    124 {
    125   WRITE_MSG(1,
    126 	    "ncontext " VERSION " -- manages the creation of network contexts\n"
    127 	    "This program is part of " PACKAGE_STRING "\n\n"
    128 	    "Copyright (C) 2004-2006 Enrico Scholz\n"
    129 	    "Copyright (C) 2006 Daniel Hokka Zakrisson\n"
    130 	    VERSION_COPYRIGHT_DISCLAIMER);
    131   exit(0);
    132 }
    133 
    134 #include "context-sync.hc"
    135 
    136 static inline ALWAYSINLINE void
    137 tellContext(nid_t nid, bool do_it)
    138 {
    139   char		buf[sizeof(nid_t)*3+2];
    140   size_t	l;
    141 
    142   if (!do_it) return;
    143 
    144   l = utilvserver_fmt_long(buf,nid);
    145 
    146   WRITE_MSG(1, "New network context is ");
    147   Vwrite   (1, buf, l);
    148   WRITE_MSG(1, "\n");
    149 }
    150 
    151 static int
    152 connectExternalSync(char const *filename)
    153 {
    154   int			fd;
    155   struct sockaddr_un	addr;
    156   
    157   if (filename==0) return -1;
    158 
    159   ENSC_INIT_UNIX_SOCK(addr, filename);
    160 
    161   fd = Esocket(PF_UNIX, SOCK_STREAM, 0);
    162   Econnect(fd, &addr, sizeof(addr));
    163 
    164   return fd;
    165 }
    166 
    167 static void
    168 doExternalSync(int fd, char const *msg)
    169 {
    170   char		c;
    171   
    172   if (fd==-1) return;
    173 
    174   if (msg) EsendAll(fd, msg, strlen(msg));
    175   Eshutdown(fd, SHUT_WR);
    176 
    177   if (TEMP_FAILURE_RETRY(recv(fd, &c, 1, MSG_NOSIGNAL))!=0) {
    178     WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "unexpected external synchronization event\n");
    179     exit(wrapper_exit_code);
    180   }
    181 
    182   Eclose(fd);
    183 }
    184 
    185 static inline ALWAYSINLINE int
    186 doit(struct Arguments const *args, char *argv[])
    187 {
    188   int			p[2][2];
    189   pid_t			pid = initSync(p, args->do_disconnect);
    190   
    191   if (pid==0) {
    192     nid_t			nid;
    193     int				ext_sync_fd = connectExternalSync(args->sync_sock);
    194 
    195     doSyncStage0(p, args->do_disconnect);  
    196     
    197     if (args->do_create) {
    198       nid = vc_net_create(args->nid);
    199       if (nid==VC_NOCTX) {
    200 	switch (errno) {
    201 	  case EEXIST	:
    202 	    if (!args->is_silentexist)
    203 	      perror(ENSC_WRAPPERS_PREFIX "vc_net_create()");
    204 	    return 254;
    205 	  default	:
    206 	    perror(ENSC_WRAPPERS_PREFIX "vc_net_create()");
    207 	    return wrapper_exit_code;
    208 	}
    209       }
    210       tellContext(nid, args->verbosity>=1);
    211     }
    212     else
    213       nid = args->nid;
    214 
    215     if (args->do_migrate && !args->do_migrateself)
    216       Evc_net_migrate(nid);
    217 
    218     doExternalSync(ext_sync_fd, args->sync_msg);
    219     doSyncStage1(p, args->do_disconnect);
    220     DPRINTF("doit: pid=%u, ppid=%u\n", getpid(), getppid());
    221     execvp (argv[optind],argv+optind);
    222     doSyncStage2(p, args->do_disconnect);
    223 
    224     PERROR_Q(ENSC_WRAPPERS_PREFIX "execvp", argv[optind]);
    225     exit(wrapper_exit_code);
    226   }
    227 
    228   assert(args->do_disconnect);
    229     
    230   waitOnSync(pid, p, args->nid!=VC_DYNAMIC_XID && args->do_migrate);
    231   return EXIT_SUCCESS;
    232 }
    233 
    234 int main (int argc, char *argv[])
    235 {
    236   struct Arguments		args = {
    237     .nid               = VC_DYNAMIC_XID,
    238     .do_create         = false,
    239     .do_migrate        = false,
    240     .do_migrateself    = false,
    241     .do_disconnect     = false,
    242     .is_silentexist    = false,
    243     .verbosity         = 1,
    244     .sync_msg          = "ok",
    245   };
    246   
    247   while (1) {
    248     int		c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
    249     if (c==-1) break;
    250     
    251     switch (c) {
    252       case CMD_HELP		:  showHelp(1, argv[0], 0);
    253       case CMD_VERSION		:  showVersion();
    254       case CMD_CREATE		:  args.do_create      = true;   break;
    255       case CMD_MIGRATE		:  args.do_migrate     = true;   break;
    256       case CMD_DISCONNECT	:  args.do_disconnect  = true;   break;
    257       case CMD_SILENTEXIST	:  args.is_silentexist = true;   break;
    258       case CMD_SYNCSOCK		:  args.sync_sock      = optarg; break;
    259       case CMD_SYNCMSG		:  args.sync_msg       = optarg; break;
    260       case CMD_NID		:  args.nid = Evc_nidopt2nid(optarg,true); break;
    261       case CMD_SILENT		:  --args.verbosity; break;
    262       case CMD_MIGRATESELF	:
    263 	args.do_migrate     = true;
    264 	args.do_migrateself = true;
    265 	break;
    266 
    267       default		:
    268 	WRITE_MSG(2, "Try '");
    269 	WRITE_STR(2, argv[0]);
    270 	WRITE_MSG(2, " --help' for more information.\n");
    271 	return wrapper_exit_code;
    272 	break;
    273     }
    274   }
    275 
    276   signal(SIGCHLD, SIG_DFL);
    277   
    278   if (args.do_migrateself)
    279     args.nid = Evc_get_task_nid(0);
    280   
    281   if (!args.do_create && !args.do_migrate)
    282     WRITE_MSG(2, "Neither '--create' nor '--migrate' specified; try '--help' for more information\n");
    283   else if (args.do_create && args.do_migrate)
    284     WRITE_MSG(2, "Can not specify '--create' and '--migrate' at the same time; try '--help' for more information\n");
    285   else if (!args.do_create && args.nid==VC_DYNAMIC_XID)
    286     WRITE_MSG(2, "Can not migrate to an unknown context\n");
    287   else if (optind>=argc)
    288     WRITE_MSG(2, "No command given; use '--help' for more information.\n");
    289   else
    290     return doit(&args, argv);
    291 
    292   return wrapper_exit_code;
    293 }