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

S.Çağlar Onur caglar at 10ur.org
Wed Nov 13 03:58:22 UTC 2013


Hi Stéphane,

On Tue, Nov 12, 2013 at 10:51 PM, Stéphane Graber <stgraber at ubuntu.com> wrote:
> 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?

Sure thing, in fact lxc-device is the reason why I come up with this
patch. I wanted to provide the same functionality to Go users and
implemented it in Go first but then I thought we can have this in the
C API and all bindings (and users) can use it. I'll try to add
alternate path to it and will re-send, assuming having this in the API
is acceptable.

>> 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



-- 
S.Çağlar Onur <caglar at 10ur.org>




More information about the lxc-devel mailing list