Hi Stéphane,

On Tue, Nov 12, 2013 at 10:51 PM, Stéphane Graber <stgra...@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 <cag...@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@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/lxc-devel
>
> --
> Stéphane Graber
> Ubuntu developer
> http://www.ubuntu.com



-- 
S.Çağlar Onur <cag...@10ur.org>

------------------------------------------------------------------------------
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@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to