github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/daemon/cluster/executor/container/executor.go (about) 1 package container 2 3 import ( 4 "fmt" 5 "sort" 6 "strings" 7 8 "github.com/Sirupsen/logrus" 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 executorpkg "github.com/docker/docker/daemon/cluster/executor" 15 clustertypes "github.com/docker/docker/daemon/cluster/provider" 16 networktypes "github.com/docker/libnetwork/types" 17 "github.com/docker/swarmkit/agent" 18 "github.com/docker/swarmkit/agent/exec" 19 "github.com/docker/swarmkit/api" 20 "github.com/docker/swarmkit/api/naming" 21 "golang.org/x/net/context" 22 ) 23 24 type executor struct { 25 backend executorpkg.Backend 26 dependencies exec.DependencyManager 27 } 28 29 // NewExecutor returns an executor from the docker client. 30 func NewExecutor(b executorpkg.Backend) exec.Executor { 31 return &executor{ 32 backend: b, 33 dependencies: agent.NewDependencyManager(), 34 } 35 } 36 37 // Describe returns the underlying node description from the docker client. 38 func (e *executor) Describe(ctx context.Context) (*api.NodeDescription, error) { 39 info, err := e.backend.SystemInfo() 40 if err != nil { 41 return nil, err 42 } 43 44 plugins := map[api.PluginDescription]struct{}{} 45 addPlugins := func(typ string, names []string) { 46 for _, name := range names { 47 plugins[api.PluginDescription{ 48 Type: typ, 49 Name: name, 50 }] = struct{}{} 51 } 52 } 53 54 // add v1 plugins 55 addPlugins("Volume", info.Plugins.Volume) 56 // Add builtin driver "overlay" (the only builtin multi-host driver) to 57 // the plugin list by default. 58 addPlugins("Network", append([]string{"overlay"}, info.Plugins.Network...)) 59 addPlugins("Authorization", info.Plugins.Authorization) 60 addPlugins("Log", info.Plugins.Log) 61 62 // add v2 plugins 63 v2Plugins, err := e.backend.PluginManager().List(filters.NewArgs()) 64 if err == nil { 65 for _, plgn := range v2Plugins { 66 for _, typ := range plgn.Config.Interface.Types { 67 if typ.Prefix != "docker" || !plgn.Enabled { 68 continue 69 } 70 plgnTyp := typ.Capability 71 switch typ.Capability { 72 case "volumedriver": 73 plgnTyp = "Volume" 74 case "networkdriver": 75 plgnTyp = "Network" 76 case "logdriver": 77 plgnTyp = "Log" 78 } 79 80 plugins[api.PluginDescription{ 81 Type: plgnTyp, 82 Name: plgn.Name, 83 }] = struct{}{} 84 } 85 } 86 } 87 88 pluginFields := make([]api.PluginDescription, 0, len(plugins)) 89 for k := range plugins { 90 pluginFields = append(pluginFields, k) 91 } 92 93 sort.Sort(sortedPlugins(pluginFields)) 94 95 // parse []string labels into a map[string]string 96 labels := map[string]string{} 97 for _, l := range info.Labels { 98 stringSlice := strings.SplitN(l, "=", 2) 99 // this will take the last value in the list for a given key 100 // ideally, one shouldn't assign multiple values to the same key 101 if len(stringSlice) > 1 { 102 labels[stringSlice[0]] = stringSlice[1] 103 } 104 } 105 106 description := &api.NodeDescription{ 107 Hostname: info.Name, 108 Platform: &api.Platform{ 109 Architecture: info.Architecture, 110 OS: info.OSType, 111 }, 112 Engine: &api.EngineDescription{ 113 EngineVersion: info.ServerVersion, 114 Labels: labels, 115 Plugins: pluginFields, 116 }, 117 Resources: &api.Resources{ 118 NanoCPUs: int64(info.NCPU) * 1e9, 119 MemoryBytes: info.MemTotal, 120 }, 121 } 122 123 return description, nil 124 } 125 126 func (e *executor) Configure(ctx context.Context, node *api.Node) error { 127 na := node.Attachment 128 if na == nil { 129 e.backend.ReleaseIngress() 130 return nil 131 } 132 133 options := types.NetworkCreate{ 134 Driver: na.Network.DriverState.Name, 135 IPAM: &network.IPAM{ 136 Driver: na.Network.IPAM.Driver.Name, 137 }, 138 Options: na.Network.DriverState.Options, 139 Ingress: true, 140 CheckDuplicate: true, 141 } 142 143 for _, ic := range na.Network.IPAM.Configs { 144 c := network.IPAMConfig{ 145 Subnet: ic.Subnet, 146 IPRange: ic.Range, 147 Gateway: ic.Gateway, 148 } 149 options.IPAM.Config = append(options.IPAM.Config, c) 150 } 151 152 _, err := e.backend.SetupIngress(clustertypes.NetworkCreateRequest{ 153 ID: na.Network.ID, 154 NetworkCreateRequest: types.NetworkCreateRequest{ 155 Name: na.Network.Spec.Annotations.Name, 156 NetworkCreate: options, 157 }, 158 }, na.Addresses[0]) 159 160 return err 161 } 162 163 // Controller returns a docker container runner. 164 func (e *executor) Controller(t *api.Task) (exec.Controller, error) { 165 dependencyGetter := agent.Restrict(e.dependencies, t) 166 167 if t.Spec.GetAttachment() != nil { 168 return newNetworkAttacherController(e.backend, t, dependencyGetter) 169 } 170 171 var ctlr exec.Controller 172 switch r := t.Spec.GetRuntime().(type) { 173 case *api.TaskSpec_Generic: 174 logrus.WithFields(logrus.Fields{ 175 "kind": r.Generic.Kind, 176 "type_url": r.Generic.Payload.TypeUrl, 177 }).Debug("custom runtime requested") 178 runtimeKind, err := naming.Runtime(t.Spec) 179 if err != nil { 180 return ctlr, err 181 } 182 switch runtimeKind { 183 case string(swarmtypes.RuntimePlugin): 184 c, err := plugin.NewController() 185 if err != nil { 186 return ctlr, err 187 } 188 ctlr = c 189 default: 190 return ctlr, fmt.Errorf("unsupported runtime type: %q", r.Generic.Kind) 191 } 192 case *api.TaskSpec_Container: 193 c, err := newController(e.backend, t, dependencyGetter) 194 if err != nil { 195 return ctlr, err 196 } 197 ctlr = c 198 default: 199 return ctlr, fmt.Errorf("unsupported runtime: %q", r) 200 } 201 202 return ctlr, nil 203 } 204 205 func (e *executor) SetNetworkBootstrapKeys(keys []*api.EncryptionKey) error { 206 nwKeys := []*networktypes.EncryptionKey{} 207 for _, key := range keys { 208 nwKey := &networktypes.EncryptionKey{ 209 Subsystem: key.Subsystem, 210 Algorithm: int32(key.Algorithm), 211 Key: make([]byte, len(key.Key)), 212 LamportTime: key.LamportTime, 213 } 214 copy(nwKey.Key, key.Key) 215 nwKeys = append(nwKeys, nwKey) 216 } 217 e.backend.SetNetworkBootstrapKeys(nwKeys) 218 219 return nil 220 } 221 222 func (e *executor) Secrets() exec.SecretsManager { 223 return e.dependencies.Secrets() 224 } 225 226 func (e *executor) Configs() exec.ConfigsManager { 227 return e.dependencies.Configs() 228 } 229 230 type sortedPlugins []api.PluginDescription 231 232 func (sp sortedPlugins) Len() int { return len(sp) } 233 234 func (sp sortedPlugins) Swap(i, j int) { sp[i], sp[j] = sp[j], sp[i] } 235 236 func (sp sortedPlugins) Less(i, j int) bool { 237 if sp[i].Type != sp[j].Type { 238 return sp[i].Type < sp[j].Type 239 } 240 return sp[i].Name < sp[j].Name 241 }