Signed-off-by: Renaud Gaubert <rgaubert@nvidia.com>
| ... | ... |
@@ -487,6 +487,41 @@ definitions: |
| 487 | 487 |
type: "integer" |
| 488 | 488 |
format: "int64" |
| 489 | 489 |
|
| 490 |
+ ResourceObject: |
|
| 491 |
+ description: "An object describing the resources which can be advertised by a node and requested by a task" |
|
| 492 |
+ type: "object" |
|
| 493 |
+ properties: |
|
| 494 |
+ NanoCPUs: |
|
| 495 |
+ type: "integer" |
|
| 496 |
+ format: "int64" |
|
| 497 |
+ MemoryBytes: |
|
| 498 |
+ type: "integer" |
|
| 499 |
+ format: "int64" |
|
| 500 |
+ GenericResources: |
|
| 501 |
+ $ref: "#/definitions/GenericResources" |
|
| 502 |
+ |
|
| 503 |
+ GenericResources: |
|
| 504 |
+ description: "User defined Resources, can be either Integer resources (e.g: SSD=3) or String resources (e.g: GPU={UUID1, UUID2})"
|
|
| 505 |
+ type: "array" |
|
| 506 |
+ items: |
|
| 507 |
+ type: "object" |
|
| 508 |
+ properties: |
|
| 509 |
+ NamedResourceSpec: |
|
| 510 |
+ type: "object" |
|
| 511 |
+ properties: |
|
| 512 |
+ Kind: |
|
| 513 |
+ type: "string" |
|
| 514 |
+ Value: |
|
| 515 |
+ type: "string" |
|
| 516 |
+ DiscreteResourceSpec: |
|
| 517 |
+ type: "object" |
|
| 518 |
+ properties: |
|
| 519 |
+ Kind: |
|
| 520 |
+ type: "string" |
|
| 521 |
+ Value: |
|
| 522 |
+ type: "integer" |
|
| 523 |
+ format: "int64" |
|
| 524 |
+ |
|
| 490 | 525 |
HealthConfig: |
| 491 | 526 |
description: "A test to perform to check that the container is healthy." |
| 492 | 527 |
type: "object" |
| ... | ... |
@@ -1702,14 +1737,7 @@ definitions: |
| 1702 | 1702 |
OS: |
| 1703 | 1703 |
type: "string" |
| 1704 | 1704 |
Resources: |
| 1705 |
- type: "object" |
|
| 1706 |
- properties: |
|
| 1707 |
- NanoCPUs: |
|
| 1708 |
- type: "integer" |
|
| 1709 |
- format: "int64" |
|
| 1710 |
- MemoryBytes: |
|
| 1711 |
- type: "integer" |
|
| 1712 |
- format: "int64" |
|
| 1705 |
+ $ref: "#/definitions/ResourceObject" |
|
| 1713 | 1706 |
Engine: |
| 1714 | 1707 |
type: "object" |
| 1715 | 1708 |
properties: |
| ... | ... |
@@ -1750,6 +1778,16 @@ definitions: |
| 1750 | 1750 |
Resources: |
| 1751 | 1751 |
NanoCPUs: 4000000000 |
| 1752 | 1752 |
MemoryBytes: 8272408576 |
| 1753 |
+ GenericResources: |
|
| 1754 |
+ - DiscreteResourceSpec: |
|
| 1755 |
+ Kind: "SSD" |
|
| 1756 |
+ Value: 3 |
|
| 1757 |
+ - NamedResourceSpec: |
|
| 1758 |
+ Kind: "GPU" |
|
| 1759 |
+ Value: "UUID1" |
|
| 1760 |
+ - NamedResourceSpec: |
|
| 1761 |
+ Kind: "GPU" |
|
| 1762 |
+ Value: "UUID2" |
|
| 1753 | 1763 |
Engine: |
| 1754 | 1764 |
EngineVersion: "17.04.0" |
| 1755 | 1765 |
Labels: |
| ... | ... |
@@ -2132,27 +2170,10 @@ definitions: |
| 2132 | 2132 |
properties: |
| 2133 | 2133 |
Limits: |
| 2134 | 2134 |
description: "Define resources limits." |
| 2135 |
- type: "object" |
|
| 2136 |
- properties: |
|
| 2137 |
- NanoCPUs: |
|
| 2138 |
- description: "CPU limit in units of 10<sup>-9</sup> CPU shares." |
|
| 2139 |
- type: "integer" |
|
| 2140 |
- format: "int64" |
|
| 2141 |
- MemoryBytes: |
|
| 2142 |
- description: "Memory limit in Bytes." |
|
| 2143 |
- type: "integer" |
|
| 2144 |
- format: "int64" |
|
| 2135 |
+ $ref: "#/definitions/ResourceObject" |
|
| 2145 | 2136 |
Reservation: |
| 2146 | 2137 |
description: "Define resources reservation." |
| 2147 |
- properties: |
|
| 2148 |
- NanoCPUs: |
|
| 2149 |
- description: "CPU reservation in units of 10<sup>-9</sup> CPU shares." |
|
| 2150 |
- type: "integer" |
|
| 2151 |
- format: "int64" |
|
| 2152 |
- MemoryBytes: |
|
| 2153 |
- description: "Memory reservation in Bytes." |
|
| 2154 |
- type: "integer" |
|
| 2155 |
- format: "int64" |
|
| 2138 |
+ $ref: "#/definitions/ResourceObject" |
|
| 2156 | 2139 |
RestartPolicy: |
| 2157 | 2140 |
description: "Specification for the restart policy which applies to containers created as part of this service." |
| 2158 | 2141 |
type: "object" |
| ... | ... |
@@ -2283,6 +2304,8 @@ definitions: |
| 2283 | 2283 |
NodeID: |
| 2284 | 2284 |
description: "The ID of the node that this task is on." |
| 2285 | 2285 |
type: "string" |
| 2286 |
+ AssignedGenericResources: |
|
| 2287 |
+ $ref: "#/definitions/GenericResources" |
|
| 2286 | 2288 |
Status: |
| 2287 | 2289 |
type: "object" |
| 2288 | 2290 |
properties: |
| ... | ... |
@@ -2362,6 +2385,16 @@ definitions: |
| 2362 | 2362 |
Gateway: "10.255.0.1" |
| 2363 | 2363 |
Addresses: |
| 2364 | 2364 |
- "10.255.0.10/16" |
| 2365 |
+ AssignedGenericResources: |
|
| 2366 |
+ - DiscreteResourceSpec: |
|
| 2367 |
+ Kind: "SSD" |
|
| 2368 |
+ Value: 3 |
|
| 2369 |
+ - NamedResourceSpec: |
|
| 2370 |
+ Kind: "GPU" |
|
| 2371 |
+ Value: "UUID1" |
|
| 2372 |
+ - NamedResourceSpec: |
|
| 2373 |
+ Kind: "GPU" |
|
| 2374 |
+ Value: "UUID2" |
|
| 2365 | 2375 |
ServiceSpec: |
| 2366 | 2376 |
description: "User modifiable configuration for a service." |
| 2367 | 2377 |
properties: |
| ... | ... |
@@ -5392,6 +5425,8 @@ paths: |
| 5392 | 5392 |
type: "string" |
| 5393 | 5393 |
MemTotal: |
| 5394 | 5394 |
type: "integer" |
| 5395 |
+ GenericResources: |
|
| 5396 |
+ $ref: "#/definitions/GenericResources" |
|
| 5395 | 5397 |
MemoryLimit: |
| 5396 | 5398 |
type: "boolean" |
| 5397 | 5399 |
NCPU: |
| ... | ... |
@@ -51,6 +51,7 @@ type Task struct {
|
| 51 | 51 |
Status TaskStatus `json:",omitempty"` |
| 52 | 52 |
DesiredState TaskState `json:",omitempty"` |
| 53 | 53 |
NetworksAttachments []NetworkAttachment `json:",omitempty"` |
| 54 |
+ GenericResources []GenericResource `json:",omitempty"` |
|
| 54 | 55 |
} |
| 55 | 56 |
|
| 56 | 57 |
// TaskSpec represents the spec of a task. |
| ... | ... |
@@ -79,8 +80,34 @@ type TaskSpec struct {
|
| 79 | 79 |
|
| 80 | 80 |
// Resources represents resources (CPU/Memory). |
| 81 | 81 |
type Resources struct {
|
| 82 |
- NanoCPUs int64 `json:",omitempty"` |
|
| 83 |
- MemoryBytes int64 `json:",omitempty"` |
|
| 82 |
+ NanoCPUs int64 `json:",omitempty"` |
|
| 83 |
+ MemoryBytes int64 `json:",omitempty"` |
|
| 84 |
+ GenericResources []GenericResource `json:",omitempty"` |
|
| 85 |
+} |
|
| 86 |
+ |
|
| 87 |
+// GenericResource represents a "user defined" resource which can |
|
| 88 |
+// be either an integer (e.g: SSD=3) or a string (e.g: SSD=sda1) |
|
| 89 |
+type GenericResource struct {
|
|
| 90 |
+ NamedResourceSpec *NamedGenericResource `json:",omitempty"` |
|
| 91 |
+ DiscreteResourceSpec *DiscreteGenericResource `json:",omitempty"` |
|
| 92 |
+} |
|
| 93 |
+ |
|
| 94 |
+// NamedGenericResource represents a "user defined" resource which is defined |
|
| 95 |
+// as a string. |
|
| 96 |
+// "Kind" is used to describe the Kind of a resource (e.g: "GPU", "FPGA", "SSD", ...) |
|
| 97 |
+// Value is used to identify the resource (GPU="UUID-1", FPGA="/dev/sdb5", ...) |
|
| 98 |
+type NamedGenericResource struct {
|
|
| 99 |
+ Kind string `json:",omitempty"` |
|
| 100 |
+ Value string `json:",omitempty"` |
|
| 101 |
+} |
|
| 102 |
+ |
|
| 103 |
+// DiscreteGenericResource represents a "user defined" resource which is defined |
|
| 104 |
+// as an integer |
|
| 105 |
+// "Kind" is used to describe the Kind of a resource (e.g: "GPU", "FPGA", "SSD", ...) |
|
| 106 |
+// Value is used to count the resource (SSD=5, HDD=3, ...) |
|
| 107 |
+type DiscreteGenericResource struct {
|
|
| 108 |
+ Kind string `json:",omitempty"` |
|
| 109 |
+ Value int64 `json:",omitempty"` |
|
| 84 | 110 |
} |
| 85 | 111 |
|
| 86 | 112 |
// ResourceRequirements represents resources requirements. |
| ... | ... |
@@ -62,6 +62,8 @@ func installCommonConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
|
| 62 | 62 |
|
| 63 | 63 |
flags.StringVar(&conf.MetricsAddress, "metrics-addr", "", "Set default address and port to serve the metrics api on") |
| 64 | 64 |
|
| 65 |
+ flags.StringVar(&conf.NodeGenericResources, "node-generic-resources", "", "user defined resources (e.g. fpga=2;gpu={UUID1,UUID2,UUID3})")
|
|
| 66 |
+ |
|
| 65 | 67 |
// "--deprecated-key-path" is to allow configuration of the key used |
| 66 | 68 |
// for the daemon ID and the deprecated image signing. It was never |
| 67 | 69 |
// exposed as a command line option but is added here to allow |
| ... | ... |
@@ -42,6 +42,7 @@ func NodeFromGRPC(n swarmapi.Node) types.Node {
|
| 42 | 42 |
if n.Description.Resources != nil {
|
| 43 | 43 |
node.Description.Resources.NanoCPUs = n.Description.Resources.NanoCPUs |
| 44 | 44 |
node.Description.Resources.MemoryBytes = n.Description.Resources.MemoryBytes |
| 45 |
+ node.Description.Resources.GenericResources = GenericResourcesFromGRPC(n.Description.Resources.Generic) |
|
| 45 | 46 |
} |
| 46 | 47 |
if n.Description.Engine != nil {
|
| 47 | 48 |
node.Description.Engine.EngineVersion = n.Description.Engine.EngineVersion |
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
"github.com/docker/docker/api/types/swarm/runtime" |
| 9 | 9 |
"github.com/docker/docker/pkg/namesgenerator" |
| 10 | 10 |
swarmapi "github.com/docker/swarmkit/api" |
| 11 |
+ "github.com/docker/swarmkit/api/genericresource" |
|
| 11 | 12 |
"github.com/gogo/protobuf/proto" |
| 12 | 13 |
gogotypes "github.com/gogo/protobuf/types" |
| 13 | 14 |
"github.com/pkg/errors" |
| ... | ... |
@@ -301,6 +302,31 @@ func annotationsFromGRPC(ann swarmapi.Annotations) types.Annotations {
|
| 301 | 301 |
return a |
| 302 | 302 |
} |
| 303 | 303 |
|
| 304 |
+// GenericResourcesFromGRPC converts a GRPC GenericResource to a GenericResource |
|
| 305 |
+func GenericResourcesFromGRPC(genericRes []*swarmapi.GenericResource) []types.GenericResource {
|
|
| 306 |
+ var generic []types.GenericResource |
|
| 307 |
+ for _, res := range genericRes {
|
|
| 308 |
+ var current types.GenericResource |
|
| 309 |
+ |
|
| 310 |
+ switch r := res.Resource.(type) {
|
|
| 311 |
+ case *swarmapi.GenericResource_DiscreteResourceSpec: |
|
| 312 |
+ current.DiscreteResourceSpec = &types.DiscreteGenericResource{
|
|
| 313 |
+ Kind: r.DiscreteResourceSpec.Kind, |
|
| 314 |
+ Value: r.DiscreteResourceSpec.Value, |
|
| 315 |
+ } |
|
| 316 |
+ case *swarmapi.GenericResource_NamedResourceSpec: |
|
| 317 |
+ current.NamedResourceSpec = &types.NamedGenericResource{
|
|
| 318 |
+ Kind: r.NamedResourceSpec.Kind, |
|
| 319 |
+ Value: r.NamedResourceSpec.Value, |
|
| 320 |
+ } |
|
| 321 |
+ } |
|
| 322 |
+ |
|
| 323 |
+ generic = append(generic, current) |
|
| 324 |
+ } |
|
| 325 |
+ |
|
| 326 |
+ return generic |
|
| 327 |
+} |
|
| 328 |
+ |
|
| 304 | 329 |
func resourcesFromGRPC(res *swarmapi.ResourceRequirements) *types.ResourceRequirements {
|
| 305 | 330 |
var resources *types.ResourceRequirements |
| 306 | 331 |
if res != nil {
|
| ... | ... |
@@ -313,8 +339,9 @@ func resourcesFromGRPC(res *swarmapi.ResourceRequirements) *types.ResourceRequir |
| 313 | 313 |
} |
| 314 | 314 |
if res.Reservations != nil {
|
| 315 | 315 |
resources.Reservations = &types.Resources{
|
| 316 |
- NanoCPUs: res.Reservations.NanoCPUs, |
|
| 317 |
- MemoryBytes: res.Reservations.MemoryBytes, |
|
| 316 |
+ NanoCPUs: res.Reservations.NanoCPUs, |
|
| 317 |
+ MemoryBytes: res.Reservations.MemoryBytes, |
|
| 318 |
+ GenericResources: GenericResourcesFromGRPC(res.Reservations.Generic), |
|
| 318 | 319 |
} |
| 319 | 320 |
} |
| 320 | 321 |
} |
| ... | ... |
@@ -322,6 +349,24 @@ func resourcesFromGRPC(res *swarmapi.ResourceRequirements) *types.ResourceRequir |
| 322 | 322 |
return resources |
| 323 | 323 |
} |
| 324 | 324 |
|
| 325 |
+// GenericResourcesToGRPC converts a GenericResource to a GRPC GenericResource |
|
| 326 |
+func GenericResourcesToGRPC(genericRes []types.GenericResource) []*swarmapi.GenericResource {
|
|
| 327 |
+ var generic []*swarmapi.GenericResource |
|
| 328 |
+ for _, res := range genericRes {
|
|
| 329 |
+ var r *swarmapi.GenericResource |
|
| 330 |
+ |
|
| 331 |
+ if res.DiscreteResourceSpec != nil {
|
|
| 332 |
+ r = genericresource.NewDiscrete(res.DiscreteResourceSpec.Kind, res.DiscreteResourceSpec.Value) |
|
| 333 |
+ } else if res.NamedResourceSpec != nil {
|
|
| 334 |
+ r = genericresource.NewString(res.NamedResourceSpec.Kind, res.NamedResourceSpec.Value) |
|
| 335 |
+ } |
|
| 336 |
+ |
|
| 337 |
+ generic = append(generic, r) |
|
| 338 |
+ } |
|
| 339 |
+ |
|
| 340 |
+ return generic |
|
| 341 |
+} |
|
| 342 |
+ |
|
| 325 | 343 |
func resourcesToGRPC(res *types.ResourceRequirements) *swarmapi.ResourceRequirements {
|
| 326 | 344 |
var reqs *swarmapi.ResourceRequirements |
| 327 | 345 |
if res != nil {
|
| ... | ... |
@@ -336,6 +381,7 @@ func resourcesToGRPC(res *types.ResourceRequirements) *swarmapi.ResourceRequirem |
| 336 | 336 |
reqs.Reservations = &swarmapi.Resources{
|
| 337 | 337 |
NanoCPUs: res.Reservations.NanoCPUs, |
| 338 | 338 |
MemoryBytes: res.Reservations.MemoryBytes, |
| 339 |
+ Generic: GenericResourcesToGRPC(res.Reservations.GenericResources), |
|
| 339 | 340 |
} |
| 340 | 341 |
|
| 341 | 342 |
} |
| ... | ... |
@@ -30,7 +30,8 @@ func TaskFromGRPC(t swarmapi.Task) (types.Task, error) {
|
| 30 | 30 |
Message: t.Status.Message, |
| 31 | 31 |
Err: t.Status.Err, |
| 32 | 32 |
}, |
| 33 |
- DesiredState: types.TaskState(strings.ToLower(t.DesiredState.String())), |
|
| 33 |
+ DesiredState: types.TaskState(strings.ToLower(t.DesiredState.String())), |
|
| 34 |
+ GenericResources: GenericResourcesFromGRPC(t.AssignedGenericResources), |
|
| 34 | 35 |
} |
| 35 | 36 |
|
| 36 | 37 |
// Meta |
| ... | ... |
@@ -25,6 +25,7 @@ import ( |
| 25 | 25 |
netconst "github.com/docker/libnetwork/datastore" |
| 26 | 26 |
"github.com/docker/swarmkit/agent/exec" |
| 27 | 27 |
"github.com/docker/swarmkit/api" |
| 28 |
+ "github.com/docker/swarmkit/api/genericresource" |
|
| 28 | 29 |
"github.com/docker/swarmkit/template" |
| 29 | 30 |
gogotypes "github.com/gogo/protobuf/types" |
| 30 | 31 |
) |
| ... | ... |
@@ -186,13 +187,16 @@ func (c *containerConfig) exposedPorts() map[nat.Port]struct{} {
|
| 186 | 186 |
} |
| 187 | 187 |
|
| 188 | 188 |
func (c *containerConfig) config() *enginecontainer.Config {
|
| 189 |
+ genericEnvs := genericresource.EnvFormat(c.task.AssignedGenericResources, "DOCKER_RESOURCE") |
|
| 190 |
+ env := append(c.spec().Env, genericEnvs...) |
|
| 191 |
+ |
|
| 189 | 192 |
config := &enginecontainer.Config{
|
| 190 | 193 |
Labels: c.labels(), |
| 191 | 194 |
StopSignal: c.spec().StopSignal, |
| 192 | 195 |
Tty: c.spec().TTY, |
| 193 | 196 |
OpenStdin: c.spec().OpenStdin, |
| 194 | 197 |
User: c.spec().User, |
| 195 |
- Env: c.spec().Env, |
|
| 198 |
+ Env: env, |
|
| 196 | 199 |
Hostname: c.spec().Hostname, |
| 197 | 200 |
WorkingDir: c.spec().Dir, |
| 198 | 201 |
Image: c.image(), |
| ... | ... |
@@ -11,6 +11,7 @@ import ( |
| 11 | 11 |
"github.com/docker/docker/api/types/network" |
| 12 | 12 |
swarmtypes "github.com/docker/docker/api/types/swarm" |
| 13 | 13 |
"github.com/docker/docker/daemon/cluster/controllers/plugin" |
| 14 |
+ "github.com/docker/docker/daemon/cluster/convert" |
|
| 14 | 15 |
executorpkg "github.com/docker/docker/daemon/cluster/executor" |
| 15 | 16 |
clustertypes "github.com/docker/docker/daemon/cluster/provider" |
| 16 | 17 |
networktypes "github.com/docker/libnetwork/types" |
| ... | ... |
@@ -119,6 +120,7 @@ func (e *executor) Describe(ctx context.Context) (*api.NodeDescription, error) {
|
| 119 | 119 |
Resources: &api.Resources{
|
| 120 | 120 |
NanoCPUs: int64(info.NCPU) * 1e9, |
| 121 | 121 |
MemoryBytes: info.MemTotal, |
| 122 |
+ Generic: convert.GenericResourcesToGRPC(info.GenericResources), |
|
| 122 | 123 |
}, |
| 123 | 124 |
} |
| 124 | 125 |
|
| ... | ... |
@@ -168,6 +168,9 @@ type CommonConfig struct {
|
| 168 | 168 |
ValuesSet map[string]interface{}
|
| 169 | 169 |
|
| 170 | 170 |
Experimental bool `json:"experimental"` // Experimental indicates whether experimental features should be exposed or not |
| 171 |
+ |
|
| 172 |
+ // Exposed node Generic Resources |
|
| 173 |
+ NodeGenericResources string `json:"node-generic-resources,omitempty"` |
|
| 171 | 174 |
} |
| 172 | 175 |
|
| 173 | 176 |
// IsValueSet returns true if a configuration value |
| ... | ... |
@@ -497,6 +500,10 @@ func Validate(config *Config) error {
|
| 497 | 497 |
} |
| 498 | 498 |
} |
| 499 | 499 |
|
| 500 |
+ if _, err := opts.ParseGenericResources(config.NodeGenericResources); err != nil {
|
|
| 501 |
+ return err |
|
| 502 |
+ } |
|
| 503 |
+ |
|
| 500 | 504 |
if defaultRuntime := config.GetDefaultRuntimeName(); defaultRuntime != "" && defaultRuntime != StockRuntimeName {
|
| 501 | 505 |
runtimes := config.GetAllRuntimes() |
| 502 | 506 |
if _, ok := runtimes[defaultRuntime]; !ok {
|
| ... | ... |
@@ -23,12 +23,14 @@ import ( |
| 23 | 23 |
"github.com/docker/docker/api" |
| 24 | 24 |
"github.com/docker/docker/api/types" |
| 25 | 25 |
containertypes "github.com/docker/docker/api/types/container" |
| 26 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 26 | 27 |
"github.com/docker/docker/container" |
| 27 | 28 |
"github.com/docker/docker/daemon/config" |
| 28 | 29 |
"github.com/docker/docker/daemon/discovery" |
| 29 | 30 |
"github.com/docker/docker/daemon/events" |
| 30 | 31 |
"github.com/docker/docker/daemon/exec" |
| 31 | 32 |
"github.com/docker/docker/daemon/logger" |
| 33 |
+ "github.com/docker/docker/opts" |
|
| 32 | 34 |
// register graph drivers |
| 33 | 35 |
_ "github.com/docker/docker/daemon/graphdriver/register" |
| 34 | 36 |
"github.com/docker/docker/daemon/initlayer" |
| ... | ... |
@@ -111,6 +113,7 @@ type Daemon struct {
|
| 111 | 111 |
defaultIsolation containertypes.Isolation // Default isolation mode on Windows |
| 112 | 112 |
clusterProvider cluster.Provider |
| 113 | 113 |
cluster Cluster |
| 114 |
+ genericResources []swarm.GenericResource |
|
| 114 | 115 |
metricsPluginListener net.Listener |
| 115 | 116 |
|
| 116 | 117 |
machineMemory uint64 |
| ... | ... |
@@ -568,6 +571,9 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe |
| 568 | 568 |
} |
| 569 | 569 |
}() |
| 570 | 570 |
|
| 571 |
+ if err := d.setGenericResources(config); err != nil {
|
|
| 572 |
+ return nil, err |
|
| 573 |
+ } |
|
| 571 | 574 |
// set up SIGUSR1 handler on Unix-like systems, or a Win32 global event |
| 572 | 575 |
// on Windows to dump Go routine stacks |
| 573 | 576 |
stackDumpDir := config.Root |
| ... | ... |
@@ -1036,6 +1042,17 @@ func (daemon *Daemon) setupInitLayer(initPath string) error {
|
| 1036 | 1036 |
return initlayer.Setup(initPath, rootIDs) |
| 1037 | 1037 |
} |
| 1038 | 1038 |
|
| 1039 |
+func (daemon *Daemon) setGenericResources(conf *config.Config) error {
|
|
| 1040 |
+ genericResources, err := opts.ParseGenericResources(conf.NodeGenericResources) |
|
| 1041 |
+ if err != nil {
|
|
| 1042 |
+ return err |
|
| 1043 |
+ } |
|
| 1044 |
+ |
|
| 1045 |
+ daemon.genericResources = genericResources |
|
| 1046 |
+ |
|
| 1047 |
+ return nil |
|
| 1048 |
+} |
|
| 1049 |
+ |
|
| 1039 | 1050 |
func setDefaultMtu(conf *config.Config) {
|
| 1040 | 1051 |
// do nothing if the config does not have the default 0 value. |
| 1041 | 1052 |
if conf.Mtu != 0 {
|
| ... | ... |
@@ -123,6 +123,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
|
| 123 | 123 |
RegistryConfig: daemon.RegistryService.ServiceConfig(), |
| 124 | 124 |
NCPU: sysinfo.NumCPU(), |
| 125 | 125 |
MemTotal: meminfo.MemTotal, |
| 126 |
+ GenericResources: daemon.genericResources, |
|
| 126 | 127 |
DockerRootDir: daemon.configStore.Root, |
| 127 | 128 |
Labels: daemon.configStore.Labels, |
| 128 | 129 |
ExperimentalBuild: daemon.configStore.Experimental, |
| ... | ... |
@@ -7,7 +7,10 @@ import ( |
| 7 | 7 |
"regexp" |
| 8 | 8 |
"strings" |
| 9 | 9 |
|
| 10 |
+ "github.com/docker/docker/api/types/swarm" |
|
| 11 |
+ "github.com/docker/docker/daemon/cluster/convert" |
|
| 10 | 12 |
units "github.com/docker/go-units" |
| 13 |
+ "github.com/docker/swarmkit/api/genericresource" |
|
| 11 | 14 |
) |
| 12 | 15 |
|
| 13 | 16 |
var ( |
| ... | ... |
@@ -325,3 +328,19 @@ func (m *MemBytes) UnmarshalJSON(s []byte) error {
|
| 325 | 325 |
*m = MemBytes(val) |
| 326 | 326 |
return err |
| 327 | 327 |
} |
| 328 |
+ |
|
| 329 |
+// ParseGenericResources parses and validates the specified string as a list of GenericResource |
|
| 330 |
+func ParseGenericResources(value string) ([]swarm.GenericResource, error) {
|
|
| 331 |
+ if value == "" {
|
|
| 332 |
+ return nil, nil |
|
| 333 |
+ } |
|
| 334 |
+ |
|
| 335 |
+ resources, err := genericresource.Parse(value) |
|
| 336 |
+ if err != nil {
|
|
| 337 |
+ return nil, err |
|
| 338 |
+ } |
|
| 339 |
+ |
|
| 340 |
+ obj := convert.GenericResourcesFromGRPC(resources) |
|
| 341 |
+ |
|
| 342 |
+ return obj, nil |
|
| 343 |
+} |