/** Find out if a container needs setting osrelease, * and set it if needed. */ static void get_osrelease(vps_res *res) { char *dist; char osrelease[MAX_OSREL_LEN] = ""; struct utsname uts; char *suffix; int len; dist = get_dist_name(&res->tmpl); if (!dist) return; read_osrelease_conf(dist, osrelease); if (osrelease[0] == '\0') { free(dist); return; } logger(1, 0, "Found osrelease %s for dist %s", osrelease, dist); free(dist); /* Check if current osrelease is sufficient */ if (uname(&uts) != 0) { logger(-1, errno, "Error in uname()"); return; } if (compare_osrelease(uts.release, osrelease) < 1) /* -1: error; 0: current version is good enough */ return; /* Yes we need to set osrelease for this container */ /* Make version look like our kernel, i.e. add suffix * like -028stab078.10 to osrelease */ if ((suffix = strchr(uts.release, '-')) != NULL) { len = sizeof(osrelease) - strlen(osrelease); strncat(osrelease, suffix, len); osrelease[sizeof(osrelease) - 1] = 0; } logger(1, 0, "Set osrelease=%s", osrelease); res->env.osrelease = strdup(osrelease); }
int vps_start_custom(vps_handler *h, envid_t veid, vps_param *param, skipFlags skip, struct mod_action *mod, env_create_FN fn, void *data) { int wait_p[2]; int old_wait_p[2]; int err_p[2]; int ret, err; char buf[64]; char *dist_name; struct sigaction act; vps_res *res = ¶m->res; dist_actions actions; memset(&actions, 0, sizeof(actions)); if (check_var(res->fs.root, "VE_ROOT is not set")) return VZ_VE_ROOT_NOTSET; if (vps_is_run(h, veid)) { logger(-1, 0, "Container is already running"); return VZ_VE_RUNNING; } if ((ret = check_ub(&res->ub))) return ret; dist_name = get_dist_name(&res->tmpl); ret = read_dist_actions(dist_name, DIST_DIR, &actions); free(dist_name); if (ret) return ret; logger(0, 0, "Starting container ..."); if (vps_is_mounted(res->fs.root)) { /* if CT is mounted -- umount first, to cleanup mount state */ vps_umount(h, veid, res->fs.root, skip); } if (!vps_is_mounted(res->fs.root)) { /* increase quota to perform setup */ quota_inc(&res->dq, 100); if ((ret = vps_mount(h, veid, &res->fs, &res->dq, skip))) return ret; quota_inc(&res->dq, -100); } /* Fedora 14/15 hacks */ if (fix_ve_devconsole(res->fs.root) != 0) return VZ_FS_BAD_TMPL; if (fix_ve_systemd(res->fs.root) != 0) return VZ_FS_BAD_TMPL; if (pipe(wait_p) < 0) { logger(-1, errno, "Can not create pipe"); return VZ_RESOURCE_ERROR; } /* old_wait_p is needed for backward compatibility with older kernels, * while for recent ones (that support CPT_SET_LOCKFD2) we use wait_p. * * If old_wait_p is closed without writing any data, it's "OK to go" * signal, and if data are received from old_wait_p it's "no go" * signal". Note that such thing doesn't work if vzctl segfaults, * because in this case the descriptor will be closed without * sending data. */ if (pipe(old_wait_p) < 0) { logger(-1, errno, "Can not create pipe"); return VZ_RESOURCE_ERROR; } if (pipe(err_p) < 0) { close(wait_p[0]); close(wait_p[1]); logger(-1, errno, "Can not create pipe"); return VZ_RESOURCE_ERROR; } sigemptyset(&act.sa_mask); act.sa_handler = SIG_IGN; act.sa_flags = 0; sigaction(SIGPIPE, &act, NULL); fix_numiptent(&res->ub); fix_cpu(&res->cpu); ret = vz_env_create(h, veid, res, wait_p, old_wait_p, err_p, fn, data); if (ret) goto err; if ((ret = vps_setup_res(h, veid, &actions, &res->fs, param, STATE_STARTING, skip, mod))) { goto err; } if (!(skip & SKIP_ACTION_SCRIPT)) { snprintf(buf, sizeof(buf), VPS_CONF_DIR "%d.%s", veid, START_PREFIX); if (stat_file(buf)) { if (vps_exec_script(h, veid, res->fs.root, NULL, NULL, buf, NULL, 0)) { ret = VZ_ACTIONSCRIPT_ERROR; goto err; } } } /* Tell the child that it's time to start /sbin/init */ err = 0; if (write(wait_p[1], &err, sizeof(err)) != sizeof(err)) logger(-1, errno, "Unable to write to waitfd to start init"); close(wait_p[1]); close(old_wait_p[1]); err: free_dist_actions(&actions); if (ret) { /* Kill environment */ logger(-1, 0, "Container start failed (try to check kernel " "messages, e.g. \"dmesg | tail\")"); /* Close wait fd without writing anything to it * to signal the child that we have failed to configure * the environment, so it should not start /sbin/init */ close(wait_p[1]); write(old_wait_p[1], &err, sizeof(err)); close(old_wait_p[1]); } else { if (!read(err_p[0], &ret, sizeof(ret))) { if (res->misc.wait == YES) { logger(0, 0, "Container start in progress" ", waiting ..."); err = vps_execFn(h, veid, res->fs.root, wait_on_fifo, NULL, 0); if (err) { logger(0, 0, "Container wait failed%s", err == VZ_EXEC_TIMEOUT ? \ " - timeout expired" : ""); ret = VZ_WAIT_FAILED; } else { logger(0, 0, "Container started" " successfully"); } } else { logger(0, 0, "Container start in progress..."); } } else { if (ret == VZ_FS_BAD_TMPL) logger(-1, 0, "Unable to start init, probably" " incorrect template"); logger(-1, 0, "Container start failed"); } } if (ret) { if (vps_is_run(h, veid)) env_stop(h, veid, res->fs.root, M_KILL); /* restore original quota values */ vps_set_quota(veid, &res->dq); if (vps_is_mounted(res->fs.root)) vps_umount(h, veid, res->fs.root, skip); } close(wait_p[0]); close(wait_p[1]); close(err_p[0]); close(err_p[1]); return ret; }