Ejemplo n.º 1
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
int vzctl2_env_layout_version(const char *path)
{
	char buf[STR_SIZE];
	char ver[16];
	int id;
	struct stat st;

	if (path == NULL)
		return 0;

	snprintf(buf, sizeof(buf), "%s/" VZCTL_VE_LAYOUT, path);
	if (lstat(buf, &st) == -1) {
		if (errno != ENOENT)
			return vzctl_err(-1, errno, "Unable to get the"
				" Container layout: failed to stat %s", buf);

		if (stat(path, &st) && errno != ENOENT)
			return vzctl_err(-1, errno, "Unable to stat %s", path);

		return 0;
	}
	if (!S_ISLNK(st.st_mode))
		return 0;
	id = readlink(buf, ver, sizeof(ver));
	if (id < 0 || id >= sizeof(ver))
		return vzctl_err(-1, errno, "Error reading Ct layout version from %s",
				buf);
	ver[id] = 0;

	if (sscanf(ver, "%d", &id) != 1)
		return vzctl_err(-1, 0, "Unknown VZFS version (%s)", ver);

	return id;
}
Ejemplo n.º 2
0
static int check_link(const char *file, int fd)
{
	struct stat st;

	if (fstat(fd, &st) < 0)
		return vzctl_err(-1, errno, "Unable to stat %s", file);

	if (!S_ISREG(st.st_mode))
		return vzctl_err(-1, 0, "password database %s is not regular file",
				file);
	return 0;
}
Ejemplo n.º 3
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
static int vzctl_check_owner_quiet(const char *ve_private, char *serverid,
		size_t size, char *ve_ownerid, size_t ve_size)
{
	char file[PATH_MAX];
	char *p;
	int len;
	FILE *fp;
	int ret;

	ret = is_shared_fs(ve_private);
	if (ret == -1) {
		if (errno == ENOENT)
			return 0;
		return VZCTL_E_SYSTEM;
	} else if (ret == 0)
		return 0;

	snprintf(file, sizeof(file), "%s/" VZCTL_VE_OWNER, ve_private);
	if ((fp = fopen(file, "r")) == NULL) {
		/* CT is not registered */
		if (errno == ENOENT)
			return 0;

		return vzctl_err(VZCTL_E_SYSTEM, errno,
			"Owner check failed, unable open file %s", file);
	}
	len = TEMP_FAILURE_RETRY(fread(ve_ownerid, 1, ve_size - 1, fp));
	fclose(fp);
	if (len == -1) {
		return vzctl_err(VZCTL_E_SYSTEM, errno,
			"Unable to read owner from %s", file);
	}
	ve_ownerid[len] = '\0';
	if ((p = strchr(ve_ownerid, '\n')) != NULL)
		*p = 0;

	if (vzctl2_get_normalized_uuid(ve_ownerid, file, sizeof(file))) {
		if (get_hostname(serverid, size - 1))
			return vzctl_err(VZCTL_E_ENV_MANAGE_DISABLED, errno,
				"Owner check failed, unable to get hostname");
	} else {
		get_serverid(serverid, size);
	}

	if (strcmp(serverid, ve_ownerid))
		return VZCTL_E_ENV_MANAGE_DISABLED;

	return 0;
}
Ejemplo n.º 4
0
static int parse_feature(struct vzctl_features_param *features, const char *str)
{
	int id, len;
	const char *p;
	struct feature_s *f;
	char name[STR_SIZE];

	p = strrchr(str, ':');
	if (p == NULL)
		goto err;

	len = p - str;
	if (len >= sizeof(name))
		len = sizeof(name) - 1;
	strncpy(name, str, len);
	name[len] = 0;
	f = find_feature(name);
	if (f == NULL)
		goto err;

	id = onoff2id(p + 1);
	if (id == -1)
		goto err;
	if (id == VZCTL_PARAM_ON)
		features->mask |= f->mask;
	features->known |= f->mask;

	return 0;
err:

	return vzctl_err(VZCTL_E_INVAL, 0, "An incorrect feature syntax: %s", str);
}
Ejemplo n.º 5
0
int vzctl2_env_set_features(struct vzctl_env_param *env, struct vzctl_feature_param *param)
{
	struct vzctl_features_param *f = env->features;

	if (check_features_mask(param->on))
		return vzctl_err(VZCTL_E_INVAL, 0, "An invalid feature on=%#llx is specified",
				param->on);
	if (check_features_mask(param->off))
		return vzctl_err(VZCTL_E_INVAL, 0, "An invalid feature off=%#llx is specified",
				param->off);

	f->mask = param->on;
	f->known = param->on | param->off;

	return 0;
}
Ejemplo n.º 6
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
static int get_hostname(char *out, int len)
{
	struct hostent *he;
	char buf[STR_SIZE];

	if (gethostname(buf, sizeof(buf) - 1))
		return vzctl_err(-1, errno, "get_hostname function returned error");

	pthread_mutex_lock(&_g_hostname_mtx);
	if (strncmp(_g_hostname, buf, strlen(buf))) {
		he = gethostbyname(buf);
		if (he != NULL)
			snprintf(_g_hostname, sizeof(_g_hostname), "%s", he->h_name);
		else if (strrchr(buf, '.'))
			snprintf(_g_hostname, sizeof(_g_hostname), "%s", buf);
		else {
			/* use name from gethostname() as is, not cached */
			snprintf(out, len, "%s", buf);
			goto out;
		}
	}
	snprintf(out, len, "%s", _g_hostname);
out:
	pthread_mutex_unlock(&_g_hostname_mtx);

	return 0;
}
Ejemplo n.º 7
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
int vzctl2_get_env_status(const ctid_t ctid, vzctl_env_status_t *status, int mask)
{
	char path[STR_SIZE];
	int ret;
	struct vzctl_env_handle *h;
	ctid_t id;
	struct stat st;
	int flags = mask == ENV_STATUS_RUNNING ? VZCTL_CONF_SKIP_PARSE : 0;

	if (vzctl2_parse_ctid(ctid, id))
		return vzctl_err(VZCTL_E_INVAL, 0, "Invalid CTID: %s", ctid);

	memset(status, 0, sizeof(struct vzctl_env_status));

	vzctl2_get_env_conf_path(id, path, sizeof(path));
	if (lstat(path, &st))
		return 0;

	h = vzctl2_env_open(ctid, flags, &ret);
	if (h == NULL)
		return ret;

	ret = vzctl2_get_env_status_info(h, status, mask);

	vzctl2_env_close(h);

	return ret;
}
Ejemplo n.º 8
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
static int get_env_ids_proc(vzctl_ids_t *ctids)
{
	FILE *fp;
	char buf[256];
	int res, classid, nproc;
	int ret;
	ctid_t ctid, id;

	if ((fp = fopen(PROC_VEINFO, "r")) == NULL)
		return vzctl_err(-2, errno, "Unabel to open" PROC_VEINFO);

	ret = 0;
	while (1) {
		if (fgets(buf, sizeof(buf), fp) == NULL) {
			if (!feof(fp))
				ret = -1;
			break;
		}

		res = sscanf(buf, "%37s %d %d", id, &classid, &nproc);
		if (res != 3 || vzctl2_parse_ctid(id, ctid) || !strcmp(id, "0"))
			continue;

		if (add_eids(ctids, ctid, ++ret)) {
			ret = -1;
			break;
		}
	}
	fclose(fp);
	return ret;
}
Ejemplo n.º 9
0
/* Authenticate the user in a the Container
 * @param id            Container id
 * @param user          User name
 * @param password      User password
 * @param gid           if >= 0 user checked to be a member of group gid.
 * @param type          0 - system, 1 - pleskadmin
 * @return
 */
int vzctl2_env_auth(struct vzctl_env_handle *h, const char *user, const char *passwd,
		int gid, int type)
{
	int is_mounted = 0;
	int pid, ret;
	struct vzctl_env_param *env;

	if (user == NULL || passwd == NULL)
		return vzctl_err(VZCTL_E_INVAL, 0, "Invalid argument");

	env = vzctl2_get_env_param(h);

	if (check_var(env->fs->ve_root, "VE_ROOT is not set"))
		 return VZCTL_E_VE_ROOT_NOTSET;

	is_mounted = vzctl2_env_is_mounted(h);
	if (!is_mounted) {
		ret = vzctl2_env_mount(h, 0);
		if (ret)
			return ret;
	}

	if (!(pid = fork())) {
		int rootfd = -1;
		if (type == 0) {
			rootfd = open("/", O_RDONLY);
			if (rootfd == -1)
				_exit(vzctl_err(VZCTL_E_SYSTEM, errno,
					"failed to open '/' "));
		}
		if ((ret = vzctl_chroot(env->fs->ve_root)) == 0) {
			if (type == 0)
				ret = userauth(user, passwd, gid, rootfd);
			else
				ret = pleskauth(user, passwd);
		}
		if (rootfd != -1)
			close(rootfd);
		_exit(ret);
	}
	ret = env_wait(pid, 0, NULL);

	if (!is_mounted)
		vzctl2_env_umount(h, 0);

	return ret;
}
Ejemplo n.º 10
0
static int escape_chroot(int rootfd)
{
	int ret = fchdir(rootfd);
	if (ret == -1)
		return vzctl_err(VZCTL_E_SYSTEM, errno, "fchdir('/') failed");
	ret = chroot(".");
	if (ret == -1)
		logger(VZCTL_E_SYSTEM, errno, "chroot('/') failed");
	return ret;
}
Ejemplo n.º 11
0
int main(int argc, char **argv)
{
	int ret;
	const char *action;
	ctid_t ctid = {};
	struct vzctl_env_handle *h;

	if (argc < 3)
		return usage();

	/* Action */
	action = argv[1];
	/* CTID */
	if (vzctl2_parse_ctid(argv[2], ctid))
		return VZCTL_E_INVAL;

	vzctl2_init_log(basename(argv[0]));
	vzctl2_set_ctx(ctid);
	if ((ret = vzctl2_lib_init()))
		return ret;

	vzctl2_set_flags(VZCTL_FLAG_DONT_USE_WRAP);

	h = vzctl2_env_open(ctid, 0, &ret);
	if (h == NULL)
		return ret;
	argc -= 3;
	argv += 3;
	if (!strcmp(action, "start"))
		ret = vzctl2_unwrap_env_start(h, argc, argv);
	else if (!strcmp(action, "stop"))
		ret = vzctl2_unwrap_env_stop(h, argc, argv);
	else if (!strcmp(action, "chkpnt"))
		ret = vzctl2_unwrap_env_chkpnt(h, argc, argv);
	else if (!strcmp(action, "restore"))
		ret = vzctl2_unwrap_env_restore(h, argc, argv);
	else if (!strcmp(action, "destroy"))
		ret = vzctl2_unwrap_env_destroy(h, argc, argv);
	else if (!strcmp(action, "create-snapshot"))
		ret = vzctl2_unwrap_env_create_snapshot(h, argc, argv);
	else if (!strcmp(action, "delete-snapshot"))
		ret = vzctl2_unwrap_env_delete_snapshot(h, argc, argv);
	else if (!strcmp(action, "switch-snapshot"))
		ret = vzctl2_unwrap_env_switch_snapshot(h, argc, argv);

	else
		ret = vzctl_err(VZCTL_E_INVAL_PARAMETER_SYNTAX, 0,
				"Unknown action: %s", action);

	vzctl2_env_close(h);

	return ret;
}
Ejemplo n.º 12
0
Archivo: util.c Proyecto: OpenVZ/vzctl
int xstrdup(char **dst, const char *src)
{
	char *t;

	if (src == NULL || *dst == src)
		return 0;
	if ((t = strdup(src)) == NULL)
		return vzctl_err(VZCTL_E_NOMEM, ENOMEM, "xstrdup");
	if (*dst != NULL)
		free(*dst);
	*dst = t;
	return 0;
}
Ejemplo n.º 13
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
static int unregister_env_conf(struct vzctl_env_handle *h)
{
	char veconf[PATH_MAX];

	get_env_conf_lockfile(h, veconf, sizeof(veconf));
	unlink(veconf);

	vzctl2_get_env_conf_path(EID(h), veconf, sizeof(veconf));
	if (unlink(veconf) && errno != ENOENT)
		return vzctl_err(VZCTL_E_SYSTEM, errno, "Failed to unlink %s", veconf);

	return 0;
}
Ejemplo n.º 14
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
int vzctl2_env_unregister(const char *path, const ctid_t ctid, int flags)
{
	int ret;
	struct vzctl_env_handle *h;

	h = vzctl2_env_open(ctid, 0, &ret);
	if (h == NULL)
		return vzctl_err(ret, 0,
			"failed to open Container %s configuration file", ctid);

	ret = vzctl2_env_unreg(h, flags);

	vzctl2_env_close(h);

	return ret;
}
Ejemplo n.º 15
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
int vzctl2_check_owner(const char *ve_private)
{
	int ret;
	char ve_host[STR_SIZE] = "";
	char host[STR_SIZE] = "";

	if (ve_private == NULL)
		return vzctl_err(VZCTL_E_VE_PRIVATE_NOTSET, 0, "Owner check failed:"
				" Container private area is not set");

	ret = vzctl_check_owner_quiet(ve_private, host, sizeof(host), ve_host, sizeof(ve_host));
	if (ret == VZCTL_E_ENV_MANAGE_DISABLED)
		logger(-1, 0, "Owner check failed on the server '%s':"
				" Container (%s) is registered for '%s'",
				host, ve_private, ve_host);
	return ret;
}
Ejemplo n.º 16
0
struct vzctl_vz_env_param *alloc_vz_env_param(void)
{
	struct vzctl_vz_env_param *env;

        if ((env = calloc(1, sizeof(struct vzctl_vz_env_param))) == NULL)
                goto err;
	if ((env->tc = alloc_tc_param()) == NULL)
		goto err;

	return env;

err:
	free_vz_env_param(env);
	vzctl_err(VZCTL_E_NOMEM, ENOMEM, "vzctl_alloc_env_param");

	return NULL;
}
Ejemplo n.º 17
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
static int add_eids(vzctl_ids_t *ctids, ctid_t ctid, unsigned cnt)
{
	void *t;

	if (cnt > ctids->size) {
		unsigned size = ctids->size + 100;

		t = realloc(ctids->ids, size * sizeof(ctid_t));
		if (t == NULL)
			return vzctl_err(-1, ENOMEM, "get_env_ids_proc");

		ctids->size = size;
		ctids->ids = t;
	}
	SET_CTID(ctids->ids[cnt - 1], ctid);

	return 0;
}
Ejemplo n.º 18
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
int vzctl2_lib_init(void)
{
	int ret;

	if (_initialized)
		return 0;

	init_env_ops();
	if (get_env_ops()->open == NULL)
		return vzctl_err(VZCTL_E_BAD_KERNEL, 0,
				"Your kernel does not support working with virtual"
				" environments or necessary modules are not loaded");
	ret = get_env_ops()->open();
	if (ret)
		return ret;

	_initialized = 1;

	return 0;
}
Ejemplo n.º 19
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
static int validate_eid(struct vzctl_env_handle *h, struct stat *veconf,
		ctid_t ctid)
{
	char conf[PATH_MAX];
	struct stat st;
	ctid_t ctid_conf;
	const char *data;

	if (vzctl2_env_get_param(h, "VEID", &data) == 0 && data != NULL)
		vzctl2_parse_ctid(data, ctid_conf);
	/* Check if VE_PRIVATE/ve.conf already registered
	 * /etc/vz/conf/ctid_conf.conf -> VE_PRIVATE/ve.conf
	 */
	if (!EMPTY_CTID(ctid_conf)) {
		vzctl2_get_env_conf_path(ctid_conf, conf, sizeof(conf));
		if (stat(conf, &st) == 0) {
			if (cmp_stat(veconf, &st) == 0)
				return vzctl_err(-1, 0, "Container is already"
					" registered with id %s", ctid_conf);
		} else if (errno != ENOENT)
			return vzctl_err(-1, errno, "Failed to stat %s", conf);
	}

	/* Check if ctid alredy used */
	vzctl2_get_env_conf_path(ctid, conf, sizeof(conf));
	if (lstat(conf, &st)) {
		if (errno == ENOENT)
			return 0;
		return vzctl_err(-1, errno, "Failed lstat %s", conf);
	} else if (!S_ISLNK(st.st_mode))
		return vzctl_err(-1, 0, "Container configuration file %s"
				" is not a link", conf);

	if (stat(conf, &st)) {
		if (errno == ENOENT)
			return 0;
		return vzctl_err(-1, errno, "Failed to stat %s", conf);
	}

	/* /etc/vz/conf/ctid.conf already exists */
	if (cmp_stat(veconf, &st) != 0 )
		return vzctl_err(-1, 0, "Error: Container ID %s is used", ctid);

	return 0;
}
Ejemplo n.º 20
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
int vzctl2_get_free_envid(unsigned *neweid, const char *dst,
		const char *unused)
{
	int i;
	struct vzctl_conf_simple conf;
	char file[STR_SIZE];
	char lckfile[STR_SIZE];
	char dstlck[PATH_MAX];
	struct stat st;
	int check_ve_private = 0;
	int check_ve_root = 0;
	int check_dst = 0;
	int fail_cnt = 0;
	int fd;
	ctid_t ctid = {};

	vzctl_parse_conf_simple(ctid, GLOBAL_CFG, &conf);

	if (conf.ve_private_orig != NULL && strstr(conf.ve_private_orig, "$VEID"))
		check_ve_private = 1;
	if (conf.ve_root_orig != NULL && strstr(conf.ve_root_orig, "$VEID"))
		check_ve_root = 1;
	if (dst != NULL && strstr(dst, "$VEID")) {
		snprintf(dstlck, sizeof(dstlck), "%s.lck", dst);
		check_dst = 1;
	}

	*neweid = 0;
	for (i = START_ID; i < INT_MAX/2 && fail_cnt < GET_FREE_ENVID_FAIL_MAX; i++) {
		ctid_t ctid = {i, };
		/* Check for VEID.conf */
		vzctl2_get_env_conf_path(ctid, file, sizeof(file));
		if (lstat(file, &st)) {
			if (errno != ENOENT) {
				logger(-1, errno, "Failed to stat %s", file);
				fail_cnt++;
				continue;
			}
		} else
			continue;
		/* lock envid */
		snprintf(lckfile, sizeof(lckfile), "%s.lck", file);
		fd = open(lckfile, O_CREAT|O_EXCL, 0644);
		if (fd == -1) {
			if (errno != EEXIST) {
				fail_cnt++;
				logger(-1, errno, "Failed to create %s", lckfile);
			}
			continue;
		}
		close(fd);

		/* check if PATH(s) exist */
		if ((check_ve_private && !is_dst_free(conf.ve_private_orig, ctid, &fail_cnt)) ||
		    (check_ve_root && !is_dst_free(conf.ve_root_orig, ctid, &fail_cnt)) ||
		    (check_dst &&
			(!is_dst_free(dst, ctid, &fail_cnt) || !is_dst_free(dstlck, ctid, &fail_cnt))))
		{
			/* unlock envid */
			unlink(lckfile);
			continue;
		}
		*neweid = i;
		break;
	}
	vzctl_free_conf_simple(&conf);

	if (*neweid == 0)
		return vzctl_err(-1, 0,  "Failed to get unused Countainer id");

	return 0;
}
Ejemplo n.º 21
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
int vzctl2_env_unreg(struct vzctl_env_handle *h, int flags)
{
	char buf[STR_SIZE];
	char host[STR_SIZE];
	int ret;
	const char *ve_root;
	const char *ve_private = h->env_param->fs->ve_private;

	/* preserve compatibility
	 * VZ_REG_SKIP_HA_CLUSTER is alias for VZ_REG_SKIP_CLUSTER
	 */
	if (flags & VZ_REG_SKIP_HA_CLUSTER)
		flags |= VZ_REG_SKIP_CLUSTER;

	if (is_env_run(h))
		return vzctl_err(VZCTL_E_ENV_RUN, 0,
			"Container is running, Stop Container before proceeding.");

	if (access(ve_private, F_OK) && errno == ENOENT) {
		ret = unregister_env_conf(h);
		if (ret)
			return ret;
		goto out;
	}

	if (vzctl2_env_layout_version(ve_private) < VZCTL_LAYOUT_4)
		return 0;

	ret = vzctl_check_owner_quiet(ve_private, buf, sizeof(buf), host, sizeof(host));
	if (ret == VZCTL_E_ENV_MANAGE_DISABLED) {
		logger(0, 0, "Owner check failed on the server '%s':"
				" Container (%s) is registered for '%s'",
				buf, ve_private, host);
		ret = unregister_env_conf(h);
		if (ret)
			return ret;
		goto out;
	} else if (ret)
		return ret;

	ve_root = h->env_param->fs->ve_root;
	if (ve_root != NULL && vzctl2_env_is_mounted(h) == 1) {
		if (vzctl2_env_umount(h, 0))
			return vzctl_err(VZCTL_E_FS_MOUNTED, 0,
				"Container is mounted, Unmount Container "
				"before proceeding.");
	}

	if (!(flags & VZ_UNREG_PRESERVE)) {
		/* Remove VEID from /ve_private/ve.conf */
		vzctl2_env_set_param(h, "VEID", NULL);
		if (vzctl2_env_save(h))
			return VZCTL_E_UNREGISTER;

		/* Remove VE_PRIVATE/.owner */
		snprintf(buf, sizeof(buf), "%s/" VZCTL_VE_OWNER, ve_private);
		unlink(buf);
	}

	/* cleanup name */
	if (h->env_param->name->name != NULL) {
		char name_path[PATH_MAX];
		char veconf[PATH_MAX];

		snprintf(veconf, sizeof(veconf), "%s/" VZCTL_VE_CONF, ve_private);
		snprintf(name_path, sizeof(name_path), ENV_NAME_DIR "%s",
				h->env_param->name->name);
		if (is_same_file(name_path, veconf))
			unlink(name_path);
	}

	/* Remove /etc/vz/conf/VEID.conf */
	unregister_env_conf(h);

	if (!(flags & VZ_REG_SKIP_CLUSTER) &&
			is_shared_fs(ve_private) &&
			shaman_del_resource(EID(h)))
		logger(0, 0,"Warning: Failed to unregister the Container on HA cluster");

out:
	vzctl2_destroy_net_stat(h, 0);
	vzctl2_send_state_evt(EID(h), VZCTL_ENV_UNREGISTERED);
	logger(0, 0, "Container unregistered succesfully");

	return 0;
}
Ejemplo n.º 22
0
Archivo: vz.c Proyecto: OpenVZ/libvzctl
/** Register Container
 * @param path		Container private data root
 * @param param		struct vzctl_reg_param
 * @param flags		registration flags
 * @return		veid or -1 in case error
 */
int vzctl2_env_register(const char *path, struct vzctl_reg_param *param, int flags)
{
	char buf[PATH_MAX];
	char veconf[STR_SIZE];
	char path_r[PATH_MAX];
	struct stat st;
	int ret, err;
	struct vzctl_env_handle *h;
	FILE *fp;
	char ve_host[STR_SIZE];
	char host[STR_SIZE];
	int owner_check_res;
	int on_pcs, on_shared;
	int ha_resource_added = 0;
	int ha_enable = 0;
	const char *data, *name;
	ctid_t ctid = {};
	ctid_t uuid = {};

	/* preserve compatibility
	 * VZ_REG_SKIP_HA_CLUSTER is alias for VZ_REG_SKIP_CLUSTER
	 */
	if (flags & VZ_REG_SKIP_HA_CLUSTER)
		flags |= VZ_REG_SKIP_CLUSTER;

	if (stat(path, &st) != 0)
		return vzctl_err(-1, errno, "Unable to stat %s", path);

	if (realpath(path, path_r) == NULL)
		return vzctl_err(-1, errno, "Failed to get realpath %s", path);

	ret = vzctl2_env_layout_version(path_r);
	if (ret == -1) {
		return -1;
	} else if (ret < VZCTL_LAYOUT_4)
		return vzctl_err(-1, 0, "Warning: Container in old data format,"
				" registration skipped.");

	snprintf(veconf, sizeof(veconf), "%s/" VZCTL_VE_CONF, path_r);
	if (stat(veconf, &st)) {
		logger(-1, 0, "Error: Broken Container, no %s file found", veconf);
		return -1;
	}

	h = vzctl2_env_open_conf(param->ctid, veconf, 0, &err);
	if (h == NULL)
		return -1;

	data = param->uuid;
	/* get UUID from config if not specified */
	if (data == NULL)
		vzctl2_env_get_param(h, "UUID", &data);

	if (get_cid_uuid_pair(param->ctid, data, ctid, uuid))
		goto err;

	owner_check_res = vzctl_check_owner_quiet(
			path_r, host, sizeof(host), ve_host, sizeof(ve_host));
	on_pcs = (is_pcs(path_r) == 1);
	on_shared = (is_shared_fs(path_r) == 1);

        if (vzctl2_env_get_param(h, "HA_ENABLE", &data) == 0 && data != NULL)
                ha_enable = yesno2id(data);

	if (on_pcs && ha_enable != VZCTL_PARAM_OFF &&
			check_external_disk(path_r, h->env_param->disk) &&
			shaman_is_configured())
	{
		logger(-1, 0, "Containers with external disks cannot be"
				" registered in a High Availability cluster");
		goto err;
	}

	if (!(flags & VZ_REG_FORCE)) {
		/* ignore renew option for pstorage (https://jira.sw.ru/browse/PSBM-16819) */
		if (on_pcs)
			flags &= ~VZ_REG_RENEW;

		if (!(flags & VZ_REG_RENEW) && owner_check_res) {
			if (owner_check_res == VZCTL_E_ENV_MANAGE_DISABLED) {
				logger(-1, 0, "Owner check failed on the server %s;"
					" Container is registered for %s", host, ve_host);
				if (on_pcs)
					logger(0, 0,
					"Failed to register the Container/virtual machine. "
					"You can force the registration, but this will revoke "
					"all access to the Container from the original server.");
			}
			goto err;
		}

		if (validate_eid(h, &st, ctid))
			goto err;
	} else if ((owner_check_res == VZCTL_E_ENV_MANAGE_DISABLED) && on_shared) {
		if (on_pcs && !(flags & VZ_REG_SKIP_CLUSTER)) {
			/* [pstorage:] if CT already registered on other node, revoke leases */
			/* before files editing (https://jira.sw.ru/browse/PSBM-16819) */
			char *argv[] = { "/usr/bin/pstorage", "revoke", "-R", (char *)path_r, NULL };
			/* it is irreversible operation */
			if (vzctl2_wrap_exec_script(argv, NULL, 0))
				goto err;
		}
		if (!(flags & VZ_REG_SKIP_CLUSTER) && (ha_enable != VZCTL_PARAM_OFF)) {
			/* remove resource from HA cluster
			 * TODO : execute 'del-everywhere' and 'add' by one command
			 *	 (https://jira.sw.ru/browse/PSBM-17374
			 */
			shaman_del_everywhere(ctid);
		}
	}
	if (!(flags & VZ_REG_SKIP_CLUSTER) && on_shared && (ha_enable != VZCTL_PARAM_OFF)) {
		/* TODO : execute 'del-everywhere' and 'add' by one command
		 *		(https://jira.sw.ru/browse/PSBM-17374)
		 * Right now ask HA cluster to register CT as resource
		 * and will do it before filesystem operations
		 */
		if (shaman_add_resource(ctid, h->conf, path_r)) {
			logger(-1, 0, "Error: Failed to register the Container %s on HA cluster",
					ctid);
			goto err;
		}
		ha_resource_added = 1;
	}

	if (!(flags & VZ_REG_SKIP_OWNER)) {
		snprintf(buf, sizeof(buf), "%s/" VZCTL_VE_OWNER, path_r);
		if ((fp = fopen(buf, "w")) == NULL) {
			logger(-1, errno, "Unable to register the Container; failed to create"
					" the file %s", buf);
			goto err;
		}
		if (get_serverid(buf, sizeof(buf)) == 0)
			fprintf(fp, "%s", buf);
		fclose(fp);
	}

	ret = renew_VE_PRIVATE(h, path, ctid);
	if (ret)
		goto err;

	/* restore CT name */
	name = param->name ?: h->env_param->name->name;
	if (name != NULL && *name != '\0') {
		ctid_t t;
		char x[PATH_MAX];
		const char *new_name = name;
		const char *veid = NULL;

		vzctl2_env_get_param(h, "VEID", &veid);

		if (vzctl2_get_envid_by_name(name, t) == 0 &&
				veid != NULL && CMP_CTID(t, veid))
		{
			logger(-1, 0, "Name %s is in use by CT %s", name, t);
			new_name = gen_uniq_name(name, x, sizeof(x));
		}

		vzctl2_env_set_param(h, "NAME", new_name);
		if (h->env_param->name->name) {
			struct stat st_n;

			snprintf(buf, sizeof(buf), ENV_NAME_DIR "%s",
					h->env_param->name->name);
			if (stat(buf, &st_n) == 0 && st.st_dev == st_n.st_dev)
				unlink(buf);
		}

		logger(0, 0, "Assign the name: %s", new_name);
		snprintf(buf, sizeof(buf), ENV_NAME_DIR "%s", new_name);
		unlink(buf);
		if (symlink(veconf, buf)) {
			logger(-1, errno, "Unable to create the link %s", buf);
			goto err;
		}
	}

	vzctl2_env_set_param(h, "VEID", ctid);
	/* Update UUID */
	vzctl2_env_set_param(h, "UUID", uuid);
	if (flags & (VZ_REG_RENEW_NETIF_IFNAME|VZ_REG_RENEW_NETIF_MAC)) {
		if (h->env_param->veth &&
				!list_empty(&h->env_param->veth->dev_list)) {
			h->env_param->veth->delall = 1;
			data = veth2str(h->env_param, h->env_param->veth, flags);
			if (data != NULL)
				vzctl2_env_set_param(h, "NETIF", data);
		}
	}

	ret = vzctl2_env_save_conf(h, veconf);
	if (ret)
		goto err;

	/* create registration */
	vzctl2_get_env_conf_path(ctid, buf, sizeof(buf));
	unlink(buf);
	if (symlink(veconf, buf)) {
		logger(-1, errno, "Failed to create the symlink %s", buf);
		goto err;
	}

	vzctl2_env_close(h);
	vzctl2_send_state_evt(ctid, VZCTL_ENV_REGISTERED);

	logger(0, 0, "Container %s was successfully registered", ctid);
	return 0;

err:
	if (ha_resource_added)
		shaman_del_resource(ctid);
	vzctl2_env_close(h);
	logger(-1, 0, "Container registration failed: %s",
			vzctl2_get_last_error());

	return -1;
}
Ejemplo n.º 23
0
int exec_container_init(struct arg_start *arg,
			struct env_create_param3 *create_param)
{
	int fd, ret;
	char *argv[] = {"init", "-z", "      ", NULL};
	char *envp[] = {"HOME=/", "TERM=linux", NULL};
	struct statfs sfs;

	/* Clear supplementary group IDs */
	setgroups(0, NULL);
	/* for 32-bit userspace running over 64-bit kernels */
	set_personality32();

	/* Create /fastboot to skip run fsck */
	fd = open("/fastboot", O_CREAT | O_RDONLY, 0644);
	if (fd >= 0)
		close(fd);

	if (arg->res->misc.wait == YES) {
		if (add_reach_runlevel_mark()) {
			ret = VZ_WAIT_FAILED;
			return -1;
		}
	}

	if (mkdir("/proc", 0555) && errno != EEXIST)
		return vzctl_err(VZ_SYSTEM_ERROR, errno,
				"Can't mkdir /proc");

	if (statfs("/proc", &sfs))
		return vzctl_err(VZ_SYSTEM_ERROR, errno,
				"statfs on /proc failed");

	if (sfs.f_type != PROC_SUPER_MAGIC &&
	    mount("proc", "/proc", "proc", 0, 0))
		return vzctl_err(VZ_SYSTEM_ERROR, errno,
				"Failed to mount /proc");

	if (stat_file("/sys") == 1)
		mount("sysfs", "/sys", "sysfs", 0, 0);

	if (create_param->feature_mask & VE_FEATURE_NFSD) {
		mount("nfsd", "/proc/fs/nfsd", "nfsd", 0, 0);
		make_dir("/var/lib/nfs/rpc_pipefs", 1);
		mount("sunrpc", "/var/lib/nfs/rpc_pipefs", "rpc_pipefs", 0, 0);
	}
	write_val("/proc/sys/net/ipv6/conf/all/forwarding", "0");

	/* Close status descriptor to report that
	 * environment is created.
	*/
	close(STDIN_FILENO);
	/* Now we wait until CT setup will be done
	   If no error, then start init, otherwise exit.
	*/

	if (read(arg->wait_p, &ret, sizeof(ret)) == 0)
		return -1;

	if ((fd = open("/dev/null", O_RDWR)) != -1) {
		dup2(fd, 0);
		dup2(fd, 1);
		dup2(fd, 2);
		close(fd);
	}

	logger(10, 0, "Starting init");

	close_fds(0, arg->err_p, -1);

	execve("/sbin/init", argv, envp);
	execve("/etc/init", argv, envp);
	execve("/bin/init", argv, envp);
	ret = VZ_FS_BAD_TMPL;
	write(arg->err_p, &ret, sizeof(ret));
	return ret;
}