github.com/rita33cool1/iot-system-gateway@v0.0.0-20200911033302-e65bde238cc5/docker-engine/daemon/cluster/executor/container/executor.go (about) 1 package container // import "github.com/docker/docker/daemon/cluster/executor/container" 2 3 import ( 4 "fmt" 5 "sort" 6 "strings" 7 "sync" 8 9 "github.com/docker/docker/api/types" 10 "github.com/docker/docker/api/types/filters" 11 "github.com/docker/docker/api/types/network" 12 swarmtypes "github.com/docker/docker/api/types/swarm" 13 "github.com/docker/docker/daemon/cluster/controllers/plugin" 14 "github.com/docker/docker/daemon/cluster/convert" 15 executorpkg "github.com/docker/docker/daemon/cluster/executor" 16 clustertypes "github.com/docker/docker/daemon/cluster/provider" 17 networktypes "github.com/docker/libnetwork/types" 18 "github.com/docker/swarmkit/agent" 19 "github.com/docker/swarmkit/agent/exec" 20 "github.com/docker/swarmkit/api" 21 "github.com/docker/swarmkit/api/naming" 22 "github.com/docker/swarmkit/template" 23 "github.com/sirupsen/logrus" 24 "golang.org/x/net/context" 25 ) 26 27 type executor struct { 28 backend executorpkg.Backend 29 pluginBackend plugin.Backend 30 dependencies exec.DependencyManager 31 mutex sync.Mutex // This mutex protects the following node field 32 node *api.NodeDescription 33 } 34 35 // NewExecutor returns an executor from the docker client. 36 func NewExecutor(b executorpkg.Backend, p plugin.Backend) exec.Executor { 37 return &executor{ 38 backend: b, 39 pluginBackend: p, 40 dependencies: agent.NewDependencyManager(), 41 } 42 } 43 44 // Describe returns the underlying node description from the docker client. 45 func (e *executor) Describe(ctx context.Context) (*api.NodeDescription, error) { 46 info, err := e.backend.SystemInfo() 47 if err != nil { 48 return nil, err 49 } 50 51 plugins := map[api.PluginDescription]struct{}{} 52 addPlugins := func(typ string, names []string) { 53 for _, name := range names { 54 plugins[api.PluginDescription{ 55 Type: typ, 56 Name: name, 57 }] = struct{}{} 58 } 59 } 60 61 // add v1 plugins 62 addPlugins("Volume", info.Plugins.Volume) 63 // Add builtin driver "overlay" (the only builtin multi-host driver) to 64 // the plugin list by default. 65 addPlugins("Network", append([]string{"overlay"}, info.Plugins.Network...)) 66 addPlugins("Authorization", info.Plugins.Authorization) 67 addPlugins("Log", info.Plugins.Log) 68 69 // add v2 plugins 70 v2Plugins, err := e.backend.PluginManager().List(filters.NewArgs()) 71 if err == nil { 72 for _, plgn := range v2Plugins { 73 for _, typ := range plgn.Config.Interface.Types { 74 if typ.Prefix != "docker" || !plgn.Enabled { 75 continue 76 } 77 plgnTyp := typ.Capability 78 switch typ.Capability { 79 case "volumedriver": 80 plgnTyp = "Volume" 81 case "networkdriver": 82 plgnTyp = "Network" 83 case "logdriver": 84 plgnTyp = "Log" 85 } 86 87 plugins[api.PluginDescription{ 88 Type: plgnTyp, 89 Name: plgn.Name, 90 }] = struct{}{} 91 } 92 } 93 } 94 95 pluginFields := make([]api.PluginDescription, 0, len(plugins)) 96 for k := range plugins { 97 pluginFields = append(pluginFields, k) 98 } 99 100 sort.Sort(sortedPlugins(pluginFields)) 101 102 // parse []string labels into a map[string]string 103 labels := map[string]string{} 104 for _, l := range info.Labels { 105 stringSlice := strings.SplitN(l, "=", 2) 106 // this will take the last value in the list for a given key 107 // ideally, one shouldn't assign multiple values to the same key 108 if len(stringSlice) > 1 { 109 labels[stringSlice[0]] = stringSlice[1] 110 } 111 } 112 113 description := &api.NodeDescription{ 114 Hostname: info.Name, 115 Platform: &api.Platform{ 116 Architecture: info.Architecture, 117 OS: info.OSType, 118 }, 119 Engine: &api.EngineDescription{ 120 EngineVersion: info.ServerVersion, 121 Labels: labels, 122 Plugins: pluginFields, 123 }, 124 Resources: &api.Resources{ 125 NanoCPUs: int64(info.NCPU) * 1e9, 126 MemoryBytes: info.MemTotal, 127 Generic: convert.GenericResourcesToGRPC(info.GenericResources), 128 }, 129 } 130 131 // Save the node information in the executor field 132 e.mutex.Lock() 133 e.node = description 134 e.mutex.Unlock() 135 136 return description, nil 137 } 138 139 func (e *executor) Configure(ctx context.Context, node *api.Node) error { 140 var ingressNA *api.NetworkAttachment 141 attachments := make(map[string]string) 142 143 for _, na := range node.Attachments { 144 if na == nil || na.Network == nil || len(na.Addresses) == 0 { 145 // this should not happen, but we got a panic here and don't have a 146 // good idea about what the underlying data structure looks like. 147 logrus.WithField("NetworkAttachment", fmt.Sprintf("%#v", na)). 148 Warnf("skipping nil or malformed node network attachment entry") 149 continue 150 } 151 152 if na.Network.Spec.Ingress { 153 ingressNA = na 154 } 155 156 attachments[na.Network.ID] = na.Addresses[0] 157 } 158 159 if (ingressNA == nil) && (node.Attachment != nil) && (len(node.Attachment.Addresses) > 0) { 160 ingressNA = node.Attachment 161 attachments[ingressNA.Network.ID] = ingressNA.Addresses[0] 162 } 163 164 if ingressNA == nil { 165 e.backend.ReleaseIngress() 166 return e.backend.GetAttachmentStore().ResetAttachments(attachments) 167 } 168 169 options := types.NetworkCreate{ 170 Driver: ingressNA.Network.DriverState.Name, 171 IPAM: &network.IPAM{ 172 Driver: ingressNA.Network.IPAM.Driver.Name, 173 }, 174 Options: ingressNA.Network.DriverState.Options, 175 Ingress: true, 176 CheckDuplicate: true, 177 } 178 179 for _, ic := range ingressNA.Network.IPAM.Configs { 180 c := network.IPAMConfig{ 181 Subnet: ic.Subnet, 182 IPRange: ic.Range, 183 Gateway: ic.Gateway, 184 } 185 options.IPAM.Config = append(options.IPAM.Config, c) 186 } 187 188 _, err := e.backend.SetupIngress(clustertypes.NetworkCreateRequest{ 189 ID: ingressNA.Network.ID, 190 NetworkCreateRequest: types.NetworkCreateRequest{ 191 Name: ingressNA.Network.Spec.Annotations.Name, 192 NetworkCreate: options, 193 }, 194 }, ingressNA.Addresses[0]) 195 if err != nil { 196 return err 197 } 198 199 return e.backend.GetAttachmentStore().ResetAttachments(attachments) 200 } 201 202 // Controller returns a docker container runner. 203 func (e *executor) Controller(t *api.Task) (exec.Controller, error) { 204 dependencyGetter := template.NewTemplatedDependencyGetter(agent.Restrict(e.dependencies, t), t, nil) 205 206 // Get the node description from the executor field 207 e.mutex.Lock() 208 nodeDescription := e.node 209 e.mutex.Unlock() 210 211 if t.Spec.GetAttachment() != nil { 212 return newNetworkAttacherController(e.backend, t, nodeDescription, dependencyGetter) 213 } 214 215 var ctlr exec.Controller 216 switch r := t.Spec.GetRuntime().(type) { 217 case *api.TaskSpec_Generic: 218 logrus.WithFields(logrus.Fields{ 219 "kind": r.Generic.Kind, 220 "type_url": r.Generic.Payload.TypeUrl, 221 }).Debug("custom runtime requested") 222 runtimeKind, err := naming.Runtime(t.Spec) 223 if err != nil { 224 return ctlr, err 225 } 226 switch runtimeKind { 227 case string(swarmtypes.RuntimePlugin): 228 info, _ := e.backend.SystemInfo() 229 if !info.ExperimentalBuild { 230 return ctlr, fmt.Errorf("runtime type %q only supported in experimental", swarmtypes.RuntimePlugin) 231 } 232 c, err := plugin.NewController(e.pluginBackend, t) 233 if err != nil { 234 return ctlr, err 235 } 236 ctlr = c 237 default: 238 return ctlr, fmt.Errorf("unsupported runtime type: %q", runtimeKind) 239 } 240 case *api.TaskSpec_Container: 241 c, err := newController(e.backend, t, nodeDescription, dependencyGetter) 242 if err != nil { 243 return ctlr, err 244 } 245 ctlr = c 246 default: 247 return ctlr, fmt.Errorf("unsupported runtime: %q", r) 248 } 249 250 return ctlr, nil 251 } 252 253 func (e *executor) SetNetworkBootstrapKeys(keys []*api.EncryptionKey) error { 254 nwKeys := []*networktypes.EncryptionKey{} 255 for _, key := range keys { 256 nwKey := &networktypes.EncryptionKey{ 257 Subsystem: key.Subsystem, 258 Algorithm: int32(key.Algorithm), 259 Key: make([]byte, len(key.Key)), 260 LamportTime: key.LamportTime, 261 } 262 copy(nwKey.Key, key.Key) 263 nwKeys = append(nwKeys, nwKey) 264 } 265 e.backend.SetNetworkBootstrapKeys(nwKeys) 266 267 return nil 268 } 269 270 func (e *executor) Secrets() exec.SecretsManager { 271 return e.dependencies.Secrets() 272 } 273 274 func (e *executor) Configs() exec.ConfigsManager { 275 return e.dependencies.Configs() 276 } 277 278 type sortedPlugins []api.PluginDescription 279 280 func (sp sortedPlugins) Len() int { return len(sp) } 281 282 func (sp sortedPlugins) Swap(i, j int) { sp[i], sp[j] = sp[j], sp[i] } 283 284 func (sp sortedPlugins) Less(i, j int) bool { 285 if sp[i].Type != sp[j].Type { 286 return sp[i].Type < sp[j].Type 287 } 288 return sp[i].Name < sp[j].Name 289 }