-----------------------------------------------------------
This is an automatically generated e-mail. To reply, visit:
https://reviews.apache.org/r/44796/#review123505
-----------------------------------------------------------



This commit and https://reviews.apache.org/r/44439/ should probably be combined 
and then broken up into the follow two commits (one for the implementation and 
one for the test):

```
Added test for cgroups device entry parsing.
Added helper classes and functions for managing cgroups devices.
```

The motivation being that these helpers should probably not live inside stout.  
Stout is designed as a **platform independent** API, whereas the stuff you 
added here is very specific to cgroups on Linux.  I would suggest putting it 
into `src/linux/cgroups.{hpp,cpp}` with the rest of the cgroups stuff (as you 
alrdady have some stuff in 44439).  As for the test, I would put it at the 
bottom of `src/tests/containerizer/cgroups_tests.cp` and call it 
`TEST(CgroupsDeviceTest, ParseTest)`.

The comments on the files below are still valid, they just be moved to these 
new locations.


3rdparty/libprocess/3rdparty/stout/Makefile.am (line 29)
<https://reviews.apache.org/r/44796/#comment185734>

    Reviewboard is reporting a whitespace error here. However, I downloaded 
things locally and everything is fine.
    
    That said, this test should probably not exist in stout (nor should the 
device helpers).  See the other comments for a suggestion on where to put it 
instead.



3rdparty/libprocess/3rdparty/stout/include/Makefile.am (line 24)
<https://reviews.apache.org/r/44796/#comment185739>

    Unnecessary, with move to `src/linux/cgroups.hpp`



3rdparty/libprocess/3rdparty/stout/include/stout/device.hpp (line 25)
<https://reviews.apache.org/r/44796/#comment185740>

    Once moved to `src/linux/cgroups.hpp`, this should all exist in the 
`cgroups::devices` namespace.
    
    Also, all of the classes in this file should be declared in the `.hpp` file 
and defined in the `.cpp`.
    
    This is a similar pattern followed by `cgroups::memory::pressure::Counter`



3rdparty/libprocess/3rdparty/stout/include/stout/device.hpp (lines 26 - 31)
<https://reviews.apache.org/r/44796/#comment185742>

    I would probably embed this enum inside the `Device` class (as mentioned in 
a comment below).



3rdparty/libprocess/3rdparty/stout/include/stout/device.hpp (line 33)
<https://reviews.apache.org/r/44796/#comment185749>

    I would suggest adding a class called `DeviceEntry`, which containes 
subfields for `Selector` and `Access`.
    
    With this, a parse function in the `cgroups::devices::parse()` namespace 
can be written to parse full whitelist entries, i.e.:
    
    ```
    static Try<DeviceEntry> parse(const std::string& entry);
    ```
    
    I would also then make the `Selector` and `Access` classes structs instead 
of classes.



3rdparty/libprocess/3rdparty/stout/include/stout/device.hpp (line 35)
<https://reviews.apache.org/r/44796/#comment185751>

    I would probably not embed parse functions in the `Selector` and `Access` 
classes as you have done here.  I sugest having a global `parse()` function 
that operates on `DeviceEntry` objects as described in a previous comment.



3rdparty/libprocess/3rdparty/stout/include/stout/device.hpp (lines 37 - 40)
<https://reviews.apache.org/r/44796/#comment185743>

    We typically don't "pre-declare" variables like this in Mesos.  Instead, we 
declare them just before their first use.
    
    Also, using a size_t for index isn't really the correct type here. It 
should probably be `std::string::size_type`.



3rdparty/libprocess/3rdparty/stout/include/stout/device.hpp (lines 42 - 100)
<https://reviews.apache.org/r/44796/#comment185745>

    Assuming we move this parse function out to a global `Try<DeviceEntry> 
parse()` function, I feel we can get away sith something much simpler here. 
Something like:
    
    ```
    Try<DeviceEntry> parse(const std::string& entry)
    {
      std::vector<std::string> tokens = strings::tokenize(entry, " ");
    
      if (tokens.size() == 0) {
        return Error("Unable to parse cgroups device entry: no arguments 
provided");
      }
    
      if (token[0] == "a") {
        Selector selector(Selector::Type::ALL, "*", "*");
        Access access(true, true, true);
        return DeviceEntry(selector, access);
      }
    
      Selector selector;
      
      if (token[0] == "b") {
        selector.deviceType = Selector::Type::BLOCK;
      else if (token[0] == "c") {
        selector.deviceType = Selector::Type::CHARACTER;
      } else {
        return Error("Unable to parse cgroups device entry: unknown device 
type: ", + token[0]);
      }
      
      if (tokens.size() != 3) {
        return Error("Unable to parse cgroups device entry: not enough 
arguments for device type: ", + token[0]);
      }  
      
      Selector selector;
      selector.deviceType = token[0];
    
      std::vector<std::string> deviceNumbers = strings::tokenize(token[1], ":");
      
      if (deviceNumbers.size() != 2) {
        return Error("Unable to parse cgroups device entry: unknown device 
number: ", + token[1]);
      }
      
      Try<unsigned int> major = numify<unsigned int>(deviceNumbers[0]);
    
      if (major.isError()) {
        return Error("Unable to parse cgroups device entry: unknown major 
device: ", + deviceNumbers[0]);
      }
      
      selector.major = major.get();
      
      Try<unsigned int> minor = numify<unsigned int>(deviceNumbers[1]);
    
      if (minor.isError()) {
        return Error("Unable to parse cgroups device entry: unknown minor 
device: ", + deviceNumbers[1]);
      }
      
      selector.minor = minor.get();
      
      std::vector<std::string> access = strings::tokenize(token[2], "");
      
      if (deviceNumbers.size() > 3) {
        return Error("Unable to parse cgroups device entry: too many access 
arguments: ", + token[2]);
      }
      
      Access access;
      
      foreach (const string& permission, access) {
        if (permission == "r") {
          access.read = true;
        } else if (permission == "w") {
          access.write = true;
        } else if (permission == "m") {
          access.mkdnode = true;    
        } else {
          return Error("Unable to parse cgroups device entry: invalid 
permission: ", + permission);
        }
      }
    
      return DeviceEntry(selector, access);
    }
    ```



3rdparty/libprocess/3rdparty/stout/include/stout/device.hpp (line 50)
<https://reviews.apache.org/r/44796/#comment185744>

    I know why this works, but it is probably not clear to someone just reading 
the code as to why we just bail out here when we encounter an 'a' (even the 
cgroups docs aren't very clear on this, and you have to play around with things 
to actually discover this).
    
    I would add a comment here mentioning what's going on here.
    
    Also, I wouldn't bother setting deviceType here -- jut pass ALL directly to 
the `return Selector()` call.



3rdparty/libprocess/3rdparty/stout/include/stout/device.hpp (line 105)
<https://reviews.apache.org/r/44796/#comment185760>

    We should probably have a variabnt of this that takes all three parameters 
as inputs.



3rdparty/libprocess/3rdparty/stout/include/stout/device.hpp (lines 112 - 116)
<https://reviews.apache.org/r/44796/#comment185761>

    No need for these accessors if we make this a struct.



3rdparty/libprocess/3rdparty/stout/include/stout/device.hpp (lines 124 - 136)
<https://reviews.apache.org/r/44796/#comment185762>

    We will still need this.
    
    We will also need one for the DeviceEntry that just strems the `Selector` 
and `Access` structs out properly.



3rdparty/libprocess/3rdparty/stout/include/stout/device.hpp (lines 141 - 172)
<https://reviews.apache.org/r/44796/#comment185764>

    See above comment for DeviceEntry parser.



3rdparty/libprocess/3rdparty/stout/include/stout/device.hpp (lines 183 - 187)
<https://reviews.apache.org/r/44796/#comment185763>

    Again, no need for accessors here if this becomes a struct.



3rdparty/libprocess/3rdparty/stout/tests/CMakeLists.txt (line 25)
<https://reviews.apache.org/r/44796/#comment185736>

    Unnecessary, with a move to `src/tests/containerizer/cgroups_tests.cpp`



3rdparty/libprocess/3rdparty/stout/tests/device_tests.cpp (lines 22 - 47)
<https://reviews.apache.org/r/44796/#comment185738>

    I would probably remove the extra spaces here, like so:
    
    ```
    TEST(DeviceTest, parseTest)
    {
      Try<Selector> selector1 = Selector::parse("c *:3");
      EXPECT_EQ("c *:3", stringify(selector1.get()));
    
      Try<Selector> selector2 = Selector::parse("a");
      EXPECT_EQ("a *:*", stringify(selector2.get()));
    
      Try<Selector> selector3 = Selector::parse("za23");
      EXPECT_ERROR(selector3);
    
      Try<Selector> selector4 = Selector::parse("c 1:");
      EXPECT_ERROR(selector4);
    
      Try<Access> access1 = Access::parse("m r w");
      EXPECT_EQ("rwm", stringify(access1.get()));
    
      Try<Access> access2 = Access::parse("t r w");
      EXPECT_ERROR(access2);
    }
    ```
    
    Normally we put extra spaces to separate `EXPECT` calls from a sequence of 
operations that precede it.  However, in this case, each `EXPECT` call is 
directly tied to the one operation right above it, so it is cleaner to group 
them together.
    
    This test will obvioulsy need to be updated given the feedback above.


- Kevin Klues


On March 14, 2016, 6:22 p.m., Abhishek Dasgupta wrote:
> 
> -----------------------------------------------------------
> This is an automatically generated e-mail. To reply, visit:
> https://reviews.apache.org/r/44796/
> -----------------------------------------------------------
> 
> (Updated March 14, 2016, 6:22 p.m.)
> 
> 
> Review request for mesos, Ben Mahler, Felix Abecassis, Kevin Klues, and 
> Niklas Nielsen.
> 
> 
> Bugs: MESOS-3368
>     https://issues.apache.org/jira/browse/MESOS-3368
> 
> 
> Repository: mesos
> 
> 
> Description
> -------
> 
> Helper classes are added for device entry which is passed on to device 
> cgroups to provide devices as resources.
> 
> 
> Diffs
> -----
> 
>   3rdparty/libprocess/3rdparty/stout/Makefile.am 
> 400c6dc451602926f93b22713af8c66d7ca59ca6 
>   3rdparty/libprocess/3rdparty/stout/include/Makefile.am 
> c10c6d9d7c68a2d5b27d68736a49d212e70dcd05 
>   3rdparty/libprocess/3rdparty/stout/include/stout/device.hpp PRE-CREATION 
>   3rdparty/libprocess/3rdparty/stout/tests/CMakeLists.txt 
> 03e09fb33bf038930a2be0370883511e93f94753 
>   3rdparty/libprocess/3rdparty/stout/tests/device_tests.cpp PRE-CREATION 
> 
> Diff: https://reviews.apache.org/r/44796/diff/
> 
> 
> Testing
> -------
> 
> sudo make -j2 check GTEST_FILTER="DeviceTest.parseTest"
> 
> 
> Thanks,
> 
> Abhishek Dasgupta
> 
>

Reply via email to