[lxc-devel] [PATCH] introduce lxcapi_add_device_node and lxcapi_remove_device_node to API (v2)

Stéphane Graber stgraber at ubuntu.com
Wed Nov 13 03:51:10 UTC 2013


On Tue, Nov 12, 2013 at 10:47:06PM -0500, S.Çağlar Onur wrote:
> Adding block/char devices to running container is a common operation so
> provide a common implementation for users to consume.
> 
> changes since v2;
> * removed duplicated code
> 

lxc-device which currently implements something like that as a tool in
python also lets the user set an alternate path inside the container.
Can we have the C API offer the same feature so I can use the new API
instead of keeping my own implementation?

> Signed-off-by: S.Çağlar Onur <caglar at 10ur.org>
> ---
>  src/lxc/lxccontainer.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/lxc/lxccontainer.h |  9 ++++++
>  2 files changed, 93 insertions(+)
> 
> diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
> index 05ca643..c21bc96 100644
> --- a/src/lxc/lxccontainer.c
> +++ b/src/lxc/lxccontainer.c
> @@ -62,6 +62,8 @@
>  #endif
>  #endif
>  
> +#define MAX_BUFFER 4096
> +
>  lxc_log_define(lxc_container, lxc);
>  
>  static bool file_exists(char *f)
> @@ -2920,6 +2922,86 @@ static bool lxcapi_may_control(struct lxc_container *c)
>  	return lxc_try_cmd(c->name, c->config_path) == 0;
>  }
>  
> +static bool add_remove_device_node(struct lxc_container *c, char *src_path, bool add)
> +{
> +	int ret;
> +	struct stat st;
> +	char value[MAX_BUFFER];
> +	char dest_path[MAXPATHLEN];
> +
> +	/* make sure container is running */
> +	if (!c->is_running(c)) {
> +		ERROR("container is not running");
> +		return false;
> +	}
> +
> +	/* prepare dest_path */
> +	ret = snprintf(dest_path, MAXPATHLEN, "/proc/%d/root%s", c->init_pid(c), src_path);
> +	if (ret < 0 || ret >= MAXPATHLEN)
> +		return false;
> +
> +	if (add) {
> +		/* make sure that we can access src_path */
> +		if(access(src_path, F_OK) < 0 || stat(src_path, &st) < 0)
> +			return false;
> +	} else {
> +		/* make sure that we can access dest_path */
> +		if(access(dest_path, F_OK) < 0 || stat(dest_path, &st) < 0)
> +			return false;
> +	}
> +
> +	/* continue if path is character device or block device */
> +	if S_ISCHR(st.st_mode)
> +		ret = snprintf(value, MAX_BUFFER, "c %d:%d rwm", major(st.st_rdev), minor(st.st_rdev));
> +	else if S_ISBLK(st.st_mode)
> +		ret = snprintf(value, MAX_BUFFER, "b %d:%d rwm", major(st.st_rdev), minor(st.st_rdev));
> +	else
> +		return false;
> +
> +	/* check snprintf return code */
> +	if (ret < 0 || ret >= MAX_BUFFER)
> +		return false;
> +
> +	/* remove dest_path if it exists */
> +	if(access(dest_path, F_OK) == 0) {
> +		if (unlink(dest_path) < 0) {
> +			ERROR("unlink failed");
> +			return false;
> +		}
> +	}
> +
> +	if (add) {
> +		/* create the device node */
> +		if (mknod(dest_path, st.st_mode, st.st_rdev) < 0) {
> +			ERROR("mknod failed");
> +			return false;
> +		}
> +
> +		/* add to device list */
> +		if (!c->set_cgroup_item(c, "devices.allow", value)) {
> +			ERROR("set_cgroup_item failed while adding the device node");
> +			return false;
> +		}
> +	} else {
> +		/* remove from device list */
> +		if (!c->set_cgroup_item(c, "devices.deny", value)) {
> +			ERROR("set_cgroup_item failed while removing the device node");
> +			return false;
> +		}
> +	}
> +	return true;
> +}
> +
> +static bool lxcapi_add_device_node(struct lxc_container *c, char *path)
> +{
> +	return add_remove_device_node(c, path, true);
> +}
> +
> +static bool lxcapi_remove_device_node(struct lxc_container *c, char *path)
> +{
> +	return add_remove_device_node(c, path, false);
> +}
> +
>  static int lxcapi_attach_run_waitl(struct lxc_container *c, lxc_attach_options_t *options, const char *program, const char *arg, ...)
>  {
>  	va_list ap;
> @@ -3041,6 +3123,8 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
>  	c->snapshot_restore = lxcapi_snapshot_restore;
>  	c->snapshot_destroy = lxcapi_snapshot_destroy;
>  	c->may_control = lxcapi_may_control;
> +	c->add_device_node = lxcapi_add_device_node;
> +	c->remove_device_node = lxcapi_remove_device_node;
>  
>  	/* we'll allow the caller to update these later */
>  	if (lxc_log_init(NULL, "none", NULL, "lxc_container", 0, c->config_path)) {
> diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
> index 486035a..a94de9a 100644
> --- a/src/lxc/lxccontainer.h
> +++ b/src/lxc/lxccontainer.h
> @@ -236,6 +236,15 @@ struct lxc_container {
>  	 * and the caller may not access it.  Return true otherwise.
>  	 */
>  	bool (*may_control)(struct lxc_container *c);
> +
> +	/*
> +	 * Returns true if given device succesfully added to container
> +	 */
> +	bool (*add_device_node)(struct lxc_container *c, char *path);
> +	/*
> +	 * Returns true if given device succesfully removed from container
> +	 */
> +	bool (*remove_device_node)(struct lxc_container *c, char *path);
>  };
>  
>  struct lxc_snapshot {
> -- 
> 1.8.3.2
> 
> 
> ------------------------------------------------------------------------------
> DreamFactory - Open Source REST & JSON Services for HTML5 & Native Apps
> OAuth, Users, Roles, SQL, NoSQL, BLOB Storage and External API Access
> Free app hosting. Or install the open source package on any LAMP server.
> Sign up and see examples for AngularJS, jQuery, Sencha Touch and Native!
> http://pubads.g.doubleclick.net/gampad/clk?id=63469471&iu=/4140/ostg.clktrk
> _______________________________________________
> Lxc-devel mailing list
> Lxc-devel at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/lxc-devel

-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20131112/c5910b17/attachment.pgp>


More information about the lxc-devel mailing list