Browse code

plugins: linux capabilities and device creation

In the plugin manifest, Capabilities has been moved to
Linux.Capabilities to avoid confusion with Interface.Types[i].Capability

A DeviceCreation boolean has also been added to the manifest. This could
be changed in the future to be specific to a major number.

Signed-off-by: Tibor Vass <tibor@docker.com>
(cherry picked from commit 9f239281b1b02ed46f98af1eb39bc9b2165073fa)
Signed-off-by: Victor Vieux <victorvieux@gmail.com>

Tibor Vass authored on 2016/09/10 01:27:53
Showing 3 changed files
... ...
@@ -1311,9 +1311,10 @@ definitions:
1311 1311
           - Entrypoint
1312 1312
           - Workdir
1313 1313
           - Network
1314
-          - Capabilities
1314
+          - Linux
1315 1315
           - Mounts
1316 1316
           - Devices
1317
+          - DeviceCreation
1317 1318
           - Env
1318 1319
           - Args
1319 1320
         properties:
... ...
@@ -1361,10 +1362,15 @@ definitions:
1361 1361
               Type:
1362 1362
                 x-nullable: false
1363 1363
                 type: "string"
1364
-          Capabilities:
1365
-            type: "array"
1366
-            items:
1367
-              type: "string"
1364
+          Linux:
1365
+            type: "object"
1366
+            x-nullable: false
1367
+            required: [Capabilities]
1368
+            properties:
1369
+              Capabilities:
1370
+                type: "array"
1371
+                items:
1372
+                  type: "string"
1368 1373
           Mounts:
1369 1374
             type: "array"
1370 1375
             items:
... ...
@@ -1373,6 +1379,9 @@ definitions:
1373 1373
             type: "array"
1374 1374
             items:
1375 1375
               $ref: "#/definitions/PluginDevice"
1376
+          DeviceCreation:
1377
+            type: "boolean"
1378
+            x-nullable: false
1376 1379
           Env:
1377 1380
             type: "array"
1378 1381
             items:
... ...
@@ -39,14 +39,14 @@ type PluginConfig struct {
39 39
 	// Required: true
40 40
 	Args PluginConfigArgs `json:"Args"`
41 41
 
42
-	// capabilities
43
-	// Required: true
44
-	Capabilities []string `json:"Capabilities"`
45
-
46 42
 	// description
47 43
 	// Required: true
48 44
 	Description string `json:"Description"`
49 45
 
46
+	// device creation
47
+	// Required: true
48
+	DeviceCreation bool `json:"DeviceCreation"`
49
+
50 50
 	// devices
51 51
 	// Required: true
52 52
 	Devices []PluginDevice `json:"Devices"`
... ...
@@ -67,6 +67,10 @@ type PluginConfig struct {
67 67
 	// Required: true
68 68
 	Interface PluginConfigInterface `json:"Interface"`
69 69
 
70
+	// linux
71
+	// Required: true
72
+	Linux PluginConfigLinux `json:"Linux"`
73
+
70 74
 	// mounts
71 75
 	// Required: true
72 76
 	Mounts []PluginMount `json:"Mounts"`
... ...
@@ -117,6 +121,15 @@ type PluginConfigInterface struct {
117 117
 	Types []PluginInterfaceType `json:"Types"`
118 118
 }
119 119
 
120
+// PluginConfigLinux plugin config linux
121
+// swagger:model PluginConfigLinux
122
+type PluginConfigLinux struct {
123
+
124
+	// capabilities
125
+	// Required: true
126
+	Capabilities []string `json:"Capabilities"`
127
+}
128
+
120 129
 // PluginConfigNetwork plugin config network
121 130
 // swagger:model PluginConfigNetwork
122 131
 type PluginConfigNetwork struct {
... ...
@@ -243,11 +243,18 @@ func (p *Plugin) ComputePrivileges() types.PluginPrivileges {
243 243
 			})
244 244
 		}
245 245
 	}
246
-	if len(m.Capabilities) > 0 {
246
+	if m.DeviceCreation {
247
+		privileges = append(privileges, types.PluginPrivilege{
248
+			Name:        "device-creation",
249
+			Description: "",
250
+			Value:       []string{"true"},
251
+		})
252
+	}
253
+	if len(m.Linux.Capabilities) > 0 {
247 254
 		privileges = append(privileges, types.PluginPrivilege{
248 255
 			Name:        "capabilities",
249 256
 			Description: "",
250
-			Value:       m.Capabilities,
257
+			Value:       m.Linux.Capabilities,
251 258
 		})
252 259
 	}
253 260
 	return privileges
... ...
@@ -293,6 +300,11 @@ func (p *Plugin) InitSpec(s specs.Spec, libRoot string) (*specs.Spec, error) {
293 293
 		Readonly: false, // TODO: all plugins should be readonly? settable in config?
294 294
 	}
295 295
 
296
+	if p.PluginObj.Config.DeviceCreation {
297
+		rwm := "rwm"
298
+		s.Linux.Resources.Devices = []specs.DeviceCgroup{{Allow: true, Access: &rwm}}
299
+	}
300
+
296 301
 	mounts := append(p.PluginObj.Settings.Mounts, types.PluginMount{
297 302
 		Source:      &p.RuntimeSourcePath,
298 303
 		Destination: defaultPluginRuntimeDestination,
... ...
@@ -323,6 +335,12 @@ func (p *Plugin) InitSpec(s specs.Spec, libRoot string) (*specs.Spec, error) {
323 323
 		s.Mounts = append(s.Mounts, m)
324 324
 	}
325 325
 
326
+	for i, m := range s.Mounts {
327
+		if strings.HasPrefix(m.Destination, "/dev/") && true { // TODO: && user specified /dev
328
+			s.Mounts = append(s.Mounts[:i], s.Mounts[i+1:]...)
329
+		}
330
+	}
331
+
326 332
 	envs := make([]string, 1, len(p.PluginObj.Settings.Env)+1)
327 333
 	envs[0] = "PATH=" + system.DefaultPathEnv
328 334
 	envs = append(envs, p.PluginObj.Settings.Env...)
... ...
@@ -332,12 +350,14 @@ func (p *Plugin) InitSpec(s specs.Spec, libRoot string) (*specs.Spec, error) {
332 332
 	if len(cwd) == 0 {
333 333
 		cwd = "/"
334 334
 	}
335
-	s.Process = specs.Process{
336
-		Terminal: false,
337
-		Args:     args,
338
-		Cwd:      cwd,
339
-		Env:      envs,
340
-	}
335
+	s.Process.Terminal = false
336
+	s.Process.Args = args
337
+	s.Process.Cwd = cwd
338
+	s.Process.Env = envs
339
+
340
+	// TODO: what about duplicates?
341
+	// TODO: Should not need CAP_ prefix in manifest?
342
+	s.Process.Capabilities = append(s.Process.Capabilities, p.PluginObj.Config.Linux.Capabilities...)
341 343
 
342 344
 	return &s, nil
343 345
 }