Self update support in RS.

This commit is contained in:
Cristiano Giuffrida 2010-07-01 18:48:25 +00:00
parent 71dbe2d023
commit 03f64ac97a
4 changed files with 91 additions and 38 deletions

View file

@ -55,6 +55,8 @@ PRIVATE char *known_requests[] = {
#define RUN_CMD "run"
#define RUN_SCRIPT "/etc/rs.single" /* Default script for 'run' */
#define SELF_BINARY "self"
#define SELF_REQ_PATH "/dev/null"
#define PATH_CONFIG _PATH_SYSTEM_CONF /* Default config file */
#define DEFAULT_LU_STATE SEF_LU_STATE_WORK_FREE /* Default lu state */
#define DEFAULT_LU_MAXTIME 0 /* Default lu max time */
@ -63,6 +65,7 @@ PRIVATE char *known_requests[] = {
#define OPT_COPY "-c" /* copy executable image */
#define OPT_REUSE "-r" /* reuse executable image */
#define OPT_NOBLOCK "-n" /* unblock caller immediately */
#define OPT_REPLICA "-p" /* create replica for the service */
/* Define names for arguments provided to this utility. The first few
* arguments are required and have a known index. Thereafter, some optional
@ -104,6 +107,7 @@ PRIVATE int req_type;
PRIVATE int do_run= 0; /* 'run' command instead of 'up' */
PRIVATE char *req_label = NULL;
PRIVATE char *req_path = NULL;
PRIVATE char *req_path_self = SELF_REQ_PATH;
PRIVATE char *req_args = "";
PRIVATE int req_major = 0;
PRIVATE int req_dev_style = STYLE_NDEV;
@ -128,8 +132,8 @@ PRIVATE void print_usage(char *app_name, char *problem)
fprintf(stderr, "Warning, %s\n", problem);
fprintf(stderr, "Usage:\n");
fprintf(stderr,
" %s [%s %s %s] (up|run|update) <binary> [%s <args>] [%s <special>] [%s <style>] [%s <ticks>] [%s <path>] [%s <name>] [%s <path>] [%s <state>] [%s <time>]\n",
app_name, OPT_COPY, OPT_REUSE, OPT_NOBLOCK,
" %s [%s %s %s %s] (up|run|update) <binary|%s> [%s <args>] [%s <special>] [%s <style>] [%s <ticks>] [%s <path>] [%s <name>] [%s <path>] [%s <state>] [%s <time>]\n",
app_name, OPT_COPY, OPT_REUSE, OPT_NOBLOCK, OPT_REPLICA, SELF_BINARY,
ARG_ARGS, ARG_DEV, ARG_DEVSTYLE, ARG_PERIOD, ARG_SCRIPT,
ARG_LABELNAME, ARG_CONFIG, ARG_LU_STATE, ARG_LU_MAXTIME);
fprintf(stderr, " %s down label\n", app_name);
@ -233,6 +237,13 @@ PRIVATE int parse_arguments(int argc, char **argv)
if(p_flag)
rs_start.rss_flags |= RSS_REPLICA;
req_path = argv[optind+ARG_PATH];
if(req_nr == RS_UPDATE && !strcmp(req_path, SELF_BINARY)) {
req_config = NULL;
req_path = req_path_self;
rs_start.rss_flags |= RSS_SELF_LU;
}
if (do_run)
{
/* Set default recovery script for RUN */
@ -246,20 +257,20 @@ PRIVATE int parse_arguments(int argc, char **argv)
}
/* Verify the name of the binary of the system service. */
req_path = argv[optind+ARG_PATH];
if (req_path[0] != '/') {
print_usage(argv[ARG_NAME], "binary should be absolute path");
exit(EINVAL);
}
if (stat(req_path, &stat_buf) == -1) {
perror(req_path);
fprintf(stderr, "couldn't get stat binary\n");
exit(errno);
}
if (! (stat_buf.st_mode & S_IFREG)) {
print_usage(argv[ARG_NAME], "binary is not a regular file");
exit(EINVAL);
if(!(rs_start.rss_flags & RSS_SELF_LU)) {
if (req_path[0] != '/') {
print_usage(argv[ARG_NAME], "binary should be absolute path");
exit(EINVAL);
}
if (stat(req_path, &stat_buf) == -1) {
perror(req_path);
fprintf(stderr, "couldn't get stat binary\n");
exit(errno);
}
if (! (stat_buf.st_mode & S_IFREG)) {
print_usage(argv[ARG_NAME], "binary is not a regular file");
exit(EINVAL);
}
}
/* Get HZ. */
@ -371,6 +382,11 @@ PRIVATE int parse_arguments(int argc, char **argv)
/* no extra arguments required */
}
if((rs_start.rss_flags & RSS_SELF_LU) && !req_label) {
print_usage(argv[ARG_NAME], "label option mandatory for target action");
exit(EINVAL);
}
/* Return the request number if no error were found. */
return(req_nr);
}

View file

@ -20,6 +20,7 @@ Interface to the reincarnation server
#define RSS_REUSE 0x04 /* Try to reuse previously copied binary */
#define RSS_NOBLOCK 0x08 /* unblock caller immediately */
#define RSS_REPLICA 0x10 /* keep a replica of the service */
#define RSS_SELF_LU 0x20 /* perform self update */
/* Common definitions. */
#define RS_NR_CONTROL 8

View file

@ -292,6 +292,8 @@ PUBLIC void end_update(int result)
* service has a period, a status request will be forced in the next period.
*/
struct rproc *old_rp, *new_rp, *exiting_rp, *surviving_rp;
struct rproc **rps;
int nr_rps, i;
old_rp = rupdate.rp;
new_rp = old_rp->r_new_rp;
@ -314,14 +316,17 @@ PUBLIC void end_update(int result)
/* Send a late reply if necessary. */
late_reply(old_rp, result);
/* Unpublish and cleanup the version that has to die out and mark the other
/* Cleanup the version that has to die out and mark the other
* version as no longer updating.
*/
surviving_rp->r_flags &= ~RS_UPDATING;
cleanup_service(exiting_rp);
get_service_instances(exiting_rp, &rps, &nr_rps);
for(i=0;i<nr_rps;i++) {
cleanup_service(rps[i]);
}
if(rs_verbose)
printf("RS: service %s ended the update\n", srv_to_string(surviving_rp));
printf("RS: %s ended the update\n", srv_to_string(surviving_rp));
}
/*===========================================================================*

View file

@ -381,7 +381,7 @@ PUBLIC int do_update(message *m_ptr)
struct rproc *new_rp;
struct rprocpub *rpub;
struct rs_start rs_start;
int noblock;
int noblock, do_self_update;
int s;
char label[RS_MAX_LABEL_LEN];
int lu_state;
@ -393,6 +393,7 @@ PUBLIC int do_update(message *m_ptr)
return s;
}
noblock = (rs_start.rss_flags & RSS_NOBLOCK);
do_self_update = (rs_start.rss_flags & RSS_SELF_LU);
s = check_request(&rs_start);
if (s != OK) {
return s;
@ -442,28 +443,58 @@ PUBLIC int do_update(message *m_ptr)
return EBUSY;
}
/* Allocate a system service slot for the new version. */
s = alloc_slot(&new_rp);
if(s != OK) {
printf("RS: do_update: unable to allocate a new slot: %d\n", s);
return s;
/* A self update live updates a service instance into a replica, a regular
* update live updates a service instance into a new version, as specified
* by the given binary.
*/
if(do_self_update) {
struct rproc *r_next_rp;
if(rs_verbose)
printf("RS: %s performs self update\n", srv_to_string(rp));
/* Save information about existing replica (if any). */
r_next_rp = rp->r_next_rp;
rp->r_next_rp = NULL;
/* Clone the system service and use the replica as the new version. */
s = clone_service(rp);
if(s != OK) {
printf("RS: do_update: unable to clone service: %d\n", s);
return s;
}
new_rp = rp->r_next_rp;
new_rp->r_prev_rp = NULL;
/* Restore information about existing replica (if any). */
rp->r_next_rp = r_next_rp;
}
else {
if(rs_verbose)
printf("RS: %s performs regular update\n", srv_to_string(rp));
/* Initialize the slot as requested. */
s = init_slot(new_rp, &rs_start, m_ptr->m_source);
if(s != OK) {
printf("RS: do_update: unable to init the new slot: %d\n", s);
return s;
}
/* Allocate a system service slot for the new version. */
s = alloc_slot(&new_rp);
if(s != OK) {
printf("RS: do_update: unable to allocate a new slot: %d\n", s);
return s;
}
/* Let the new version inherit defaults from the old one. */
inherit_service_defaults(rp, new_rp);
/* Initialize the slot as requested. */
s = init_slot(new_rp, &rs_start, m_ptr->m_source);
if(s != OK) {
printf("RS: do_update: unable to init the new slot: %d\n", s);
return s;
}
/* Create new version of the service but don't let it run. */
s = create_service(new_rp);
if(s != OK) {
printf("RS: do_update: unable to create a new service: %d\n", s);
return s;
/* Let the new version inherit defaults from the old one. */
inherit_service_defaults(rp, new_rp);
/* Create new version of the service but don't let it run. */
s = create_service(new_rp);
if(s != OK) {
printf("RS: do_update: unable to create a new service: %d\n", s);
return s;
}
}
/* Link old version to new version and mark both as updating. */