func (container *Container) updateNetworkSettings(n libnetwork.Network) error { if container.NetworkSettings == nil { container.NetworkSettings = &network.Settings{Networks: []string{}} } settings := container.NetworkSettings for _, s := range settings.Networks { sn, err := container.daemon.FindNetwork(s) if err != nil { continue } if sn.Name() == n.Name() { // Avoid duplicate config return nil } if !runconfig.NetworkMode(sn.Type()).IsPrivate() || !runconfig.NetworkMode(n.Type()).IsPrivate() { return runconfig.ErrConflictSharedNetwork } if runconfig.NetworkMode(sn.Name()).IsNone() || runconfig.NetworkMode(n.Name()).IsNone() { return runconfig.ErrConflictNoNetwork } } settings.Networks = append(settings.Networks, n.Name()) return nil }
func (daemon *Daemon) updateNetworkSettings(container *Container, n libnetwork.Network) error { if container.NetworkSettings == nil { container.NetworkSettings = &network.Settings{Networks: make(map[string]*network.EndpointSettings)} } if !container.hostConfig.NetworkMode.IsHost() && runconfig.NetworkMode(n.Type()).IsHost() { return runconfig.ErrConflictHostNetwork } for s := range container.NetworkSettings.Networks { sn, err := daemon.FindNetwork(s) if err != nil { continue } if sn.Name() == n.Name() { // Avoid duplicate config return nil } if !runconfig.NetworkMode(sn.Type()).IsPrivate() || !runconfig.NetworkMode(n.Type()).IsPrivate() { return runconfig.ErrConflictSharedNetwork } if runconfig.NetworkMode(sn.Name()).IsNone() || runconfig.NetworkMode(n.Name()).IsNone() { return runconfig.ErrConflictNoNetwork } } container.NetworkSettings.Networks[n.Name()] = new(network.EndpointSettings) return nil }
func UtilCreateNetworkMode(c *check.C, networkMode string) { config := map[string]interface{}{ "Image": "busybox", "HostConfig": map[string]interface{}{"NetworkMode": networkMode}, } status, body, err := sockRequest("POST", "/containers/create", config) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusCreated) var container types.ContainerCreateResponse if err := json.Unmarshal(body, &container); err != nil { c.Fatal(err) } status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil) c.Assert(err, check.IsNil) c.Assert(status, check.Equals, http.StatusOK) var containerJSON types.ContainerJSON if err := json.Unmarshal(body, &containerJSON); err != nil { c.Fatal(err) } if containerJSON.HostConfig.NetworkMode != runconfig.NetworkMode(networkMode) { c.Fatalf("Mismatched NetworkMode, Expected %s, Actual: %s ", networkMode, containerJSON.HostConfig.NetworkMode) } }
func (container *Container) initializeNetworking() error { var err error // Make sure NetworkMode has an acceptable value before // initializing networking. if container.hostConfig.NetworkMode == runconfig.NetworkMode("") { container.hostConfig.NetworkMode = runconfig.NetworkMode("bridge") } if container.hostConfig.NetworkMode.IsContainer() { // we need to get the hosts files from the container to join nc, err := container.getNetworkedContainer() if err != nil { return err } container.HostnamePath = nc.HostnamePath container.HostsPath = nc.HostsPath container.ResolvConfPath = nc.ResolvConfPath container.Config.Hostname = nc.Config.Hostname container.Config.Domainname = nc.Config.Domainname return nil } if container.daemon.config.DisableNetwork { container.Config.NetworkDisabled = true } if container.hostConfig.NetworkMode.IsHost() { container.Config.Hostname, err = os.Hostname() if err != nil { return err } parts := strings.SplitN(container.Config.Hostname, ".", 2) if len(parts) > 1 { container.Config.Hostname = parts[0] container.Config.Domainname = parts[1] } } if err := container.AllocateNetwork(); err != nil { return err } return container.buildHostnameFile() }
func setupNetworking(netMode string, launchConfig *rancherClient.LaunchConfig) { if netMode == "" { launchConfig.NetworkMode = "managed" } else if runconfig.NetworkMode(netMode).IsContainer() { launchConfig.NetworkMode = "container" launchConfig.NetworkLaunchConfig = strings.TrimPrefix(netMode, "container:") } else { launchConfig.NetworkMode = netMode } }
// DisconnectFromNetwork disconnects container from network n. func (daemon *Daemon) DisconnectFromNetwork(container *container.Container, n libnetwork.Network) error { if !container.Running { return derr.ErrorCodeNotRunning.WithArgs(container.ID) } if container.HostConfig.NetworkMode.IsHost() && runconfig.NetworkMode(n.Type()).IsHost() { return runconfig.ErrConflictHostNetwork } return disconnectFromNetwork(container, n) }
func (daemon *Daemon) updateEndpointNetworkSettings(container *container.Container, n libnetwork.Network, ep libnetwork.Endpoint) error { if err := container.BuildEndpointInfo(n, ep); err != nil { return err } if container.HostConfig.NetworkMode == runconfig.NetworkMode("bridge") { container.NetworkSettings.Bridge = daemon.configStore.Bridge.Iface } return nil }
func (container *Container) updateEndpointNetworkSettings(n libnetwork.Network, ep libnetwork.Endpoint) error { networkSettings, err := container.buildEndpointInfo(n, ep, container.NetworkSettings) if err != nil { return err } if container.hostConfig.NetworkMode == runconfig.NetworkMode("bridge") { networkSettings.Bridge = container.daemon.configStore.Bridge.Iface } return nil }
func createLaunchConfig(r *RancherService, name string, serviceConfig *project.ServiceConfig) (rancherClient.LaunchConfig, error) { var result rancherClient.LaunchConfig rancherConfig := r.context.RancherConfig[name] schemasUrl := strings.SplitN(r.Context().Client.Schemas.Links["self"], "/schemas", 2)[0] scriptsUrl := schemasUrl + "/scripts/transform" config, hostConfig, err := docker.Convert(serviceConfig) if err != nil { return result, err } dockerContainer := &ContainerInspect{ Config: config, HostConfig: hostConfig, } dockerContainer.HostConfig.NetworkMode = runconfig.NetworkMode("") dockerContainer.Name = "/" + name err = r.Context().Client.Post(scriptsUrl, dockerContainer, &result) if err != nil { return result, err } setupNetworking(serviceConfig.Net, &result) setupVolumesFrom(serviceConfig.VolumesFrom, &result) err = setupBuild(r, name, &result, serviceConfig) if result.Labels == nil { result.Labels = map[string]interface{}{} } result.Kind = rancherConfig.Type result.Vcpu = rancherConfig.Vcpu result.Userdata = rancherConfig.Userdata result.MemoryMb = rancherConfig.Memory result.Disks = []interface{}{} for _, i := range rancherConfig.Disks { result.Disks = append(result.Disks, i) } if strings.EqualFold(result.Kind, "virtual_machine") || strings.EqualFold(result.Kind, "virtualmachine") { result.Kind = "virtualMachine" } return result, err }
func createNetwork(controller libnetwork.NetworkController, dnet string, driver string) (libnetwork.Network, error) { createOptions := []libnetwork.NetworkOption{} genericOption := options.Generic{} // Bridge driver is special due to legacy reasons if runconfig.NetworkMode(driver).IsBridge() { genericOption[netlabel.GenericData] = map[string]string{ bridge.BridgeName: dnet, } networkOption := libnetwork.NetworkOptionGeneric(genericOption) createOptions = append(createOptions, networkOption) } return controller.NewNetwork(driver, dnet, createOptions...) }
func (container *Container) allocateNetwork() error { mode := container.hostConfig.NetworkMode controller := container.daemon.netController if container.Config.NetworkDisabled || mode.IsContainer() { return nil } networkDriver := string(mode) service := container.Config.PublishService networkName := mode.NetworkName() if mode.IsDefault() { if service != "" { service, networkName, networkDriver = parseService(controller, service) } else { networkName = controller.Config().Daemon.DefaultNetwork networkDriver = controller.Config().Daemon.DefaultDriver } } else if service != "" { return derr.ErrorCodeNetworkConflict } if runconfig.NetworkMode(networkDriver).IsBridge() && container.daemon.configStore.DisableBridge { container.Config.NetworkDisabled = true return nil } if service == "" { // dot character "." has a special meaning to support SERVICE[.NETWORK] format. // For backward compatibility, replacing "." with "-", instead of failing service = strings.Replace(container.Name, ".", "-", -1) // Service names dont like "/" in them. removing it instead of failing for backward compatibility service = strings.Replace(service, "/", "", -1) } if container.secondaryNetworkRequired(networkDriver) { // Configure Bridge as secondary network for port binding purposes if err := container.configureNetwork("bridge", service, "bridge", false); err != nil { return err } } if err := container.configureNetwork(networkName, service, networkDriver, mode.IsDefault()); err != nil { return err } return container.writeHostConfig() }
// DisconnectFromNetwork disconnects a container from a network func (container *Container) DisconnectFromNetwork(n libnetwork.Network) error { if !container.Running { return derr.ErrorCodeNotRunning.WithArgs(container.ID) } if container.hostConfig.NetworkMode.IsHost() && runconfig.NetworkMode(n.Type()).IsHost() { return runconfig.ErrConflictHostNetwork } if err := container.disconnectFromNetwork(n); err != nil { return err } if err := container.toDiskLocking(); err != nil { return fmt.Errorf("Error saving container to disk: %v", err) } return nil }
func createLaunchConfig(r *RancherService, serviceConfig *project.ServiceConfig) (rancherClient.LaunchConfig, error) { var result rancherClient.LaunchConfig schemasUrl := strings.SplitN(r.Context().Client.Schemas.Links["self"], "/schemas", 2)[0] scriptsUrl := schemasUrl + "/scripts/transform" config, hostConfig, err := docker.Convert(serviceConfig) if err != nil { return result, err } dockerContainer := &ContainerInspect{ Config: config, HostConfig: hostConfig, } dockerContainer.HostConfig.NetworkMode = runconfig.NetworkMode("") if serviceConfig.Name != "" { dockerContainer.Name = "/" + serviceConfig.Name } else { dockerContainer.Name = "/" + r.name } err = r.Context().Client.Post(scriptsUrl, dockerContainer, &result) if err != nil { return result, err } result.HealthCheck = r.HealthCheck() setupNetworking(serviceConfig.Net, &result) setupVolumesFrom(serviceConfig.VolumesFrom, &result) err = r.setupBuild(&result, serviceConfig) if result.Labels == nil { result.Labels = map[string]interface{}{} } return result, err }
func (container *Container) updateEndpointNetworkSettings(n libnetwork.Network, ep libnetwork.Endpoint) error { networkSettings := &network.Settings{NetworkID: n.ID(), EndpointID: ep.ID()} networkSettings, err := container.buildPortMapInfo(ep, networkSettings) if err != nil { return err } networkSettings, err = container.buildEndpointInfo(ep, networkSettings) if err != nil { return err } if container.hostConfig.NetworkMode == runconfig.NetworkMode("bridge") { networkSettings.Bridge = container.daemon.configStore.Bridge.Iface } container.NetworkSettings = networkSettings return nil }
func UtilCreateNetworkMode(c *check.C, networkMode string) { config := map[string]interface{}{ "Image": "busybox", "HostConfig": map[string]interface{}{"NetworkMode": networkMode}, } status, body, err := sockRequest("POST", "/containers/create", config) c.Assert(err, checker.IsNil) c.Assert(status, checker.Equals, http.StatusCreated) var container types.ContainerCreateResponse c.Assert(json.Unmarshal(body, &container), checker.IsNil) status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil) c.Assert(err, checker.IsNil) c.Assert(status, checker.Equals, http.StatusOK) var containerJSON types.ContainerJSON c.Assert(json.Unmarshal(body, &containerJSON), checker.IsNil) c.Assert(containerJSON.HostConfig.NetworkMode, checker.Equals, runconfig.NetworkMode(networkMode), check.Commentf("Mismatched NetworkMode")) }
func (daemon *Daemon) connectToNetwork(container *Container, idOrName string, updateSettings bool) (err error) { if container.hostConfig.NetworkMode.IsContainer() { return runconfig.ErrConflictSharedNetwork } if runconfig.NetworkMode(idOrName).IsBridge() && daemon.configStore.DisableBridge { container.Config.NetworkDisabled = true return nil } controller := daemon.netController n, err := daemon.FindNetwork(idOrName) if err != nil { return err } if updateSettings { if err := daemon.updateNetworkSettings(container, n); err != nil { return err } } ep, err := container.getEndpointInNetwork(n) if err == nil { return fmt.Errorf("container already connected to network %s", idOrName) } if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok { return err } createOptions, err := container.buildCreateEndpointOptions(n) if err != nil { return err } endpointName := strings.TrimPrefix(container.Name, "/") ep, err = n.CreateEndpoint(endpointName, createOptions...) if err != nil { return err } defer func() { if err != nil { if e := ep.Delete(); e != nil { logrus.Warnf("Could not rollback container connection to network %s", idOrName) } } }() if err := daemon.updateEndpointNetworkSettings(container, n, ep); err != nil { return err } sb := daemon.getNetworkSandbox(container) if sb == nil { options, err := daemon.buildSandboxOptions(container, n) if err != nil { return err } sb, err = controller.NewSandbox(container.ID, options...) if err != nil { return err } container.updateSandboxNetworkSettings(sb) } if err := ep.Join(sb); err != nil { return err } if err := container.updateJoinInfo(n, ep); err != nil { return derr.ErrorCodeJoinInfo.WithArgs(err) } return nil }
func Convert(c *project.ServiceConfig) (*runconfig.Config, *runconfig.HostConfig, error) { vs := Filter(c.Volumes, isVolume) volumes := make(map[string]struct{}, len(vs)) for _, v := range vs { volumes[v] = struct{}{} } ports, binding, err := nat.ParsePortSpecs(c.Ports) if err != nil { return nil, nil, err } restart, err := runconfig.ParseRestartPolicy(c.Restart) if err != nil { return nil, nil, err } if exposedPorts, _, err := nat.ParsePortSpecs(c.Expose); err != nil { return nil, nil, err } else { for k, v := range exposedPorts { ports[k] = v } } deviceMappings, err := parseDevices(c.Devices) if err != nil { return nil, nil, err } config := &runconfig.Config{ Entrypoint: runconfig.NewEntrypoint(c.Entrypoint.Slice()...), Hostname: c.Hostname, Domainname: c.DomainName, User: c.User, Env: c.Environment.Slice(), Cmd: runconfig.NewCommand(c.Command.Slice()...), Image: c.Image, Labels: c.Labels.MapParts(), ExposedPorts: ports, Tty: c.Tty, OpenStdin: c.StdinOpen, WorkingDir: c.WorkingDir, VolumeDriver: c.VolumeDriver, Volumes: volumes, } host_config := &runconfig.HostConfig{ VolumesFrom: c.VolumesFrom, CapAdd: runconfig.NewCapList(c.CapAdd), CapDrop: runconfig.NewCapList(c.CapDrop), CpuShares: c.CpuShares, CpusetCpus: c.CpuSet, ExtraHosts: c.ExtraHosts, Privileged: c.Privileged, Binds: Filter(c.Volumes, isBind), Devices: deviceMappings, Dns: c.Dns.Slice(), DnsSearch: c.DnsSearch.Slice(), LogConfig: runconfig.LogConfig{ Type: c.LogDriver, Config: c.LogOpt, }, Memory: c.MemLimit, MemorySwap: c.MemSwapLimit, NetworkMode: runconfig.NetworkMode(c.Net), ReadonlyRootfs: c.ReadOnly, PidMode: runconfig.PidMode(c.Pid), UTSMode: runconfig.UTSMode(c.Uts), IpcMode: runconfig.IpcMode(c.Ipc), PortBindings: binding, RestartPolicy: restart, SecurityOpt: c.SecurityOpt, } return config, host_config, nil }
func (container *Container) AllocateNetwork() error { mode := container.hostConfig.NetworkMode controller := container.daemon.netController if container.Config.NetworkDisabled || mode.IsContainer() { return nil } parts := strings.Split(string(mode), ":") switch { case len(parts) == 0: return nil case len(parts) == 1: case len(parts) == 2: default: return errors.New("networkname:ip not specified") } mode = runconfig.NetworkMode(parts[0]) var networkName string var networkByName = false n, err := controller.NetworkByName(String(mode)) if err == nil { networkName = string(mode) networkByName = true } else { networkName = mode.NetworkName } networkDriver := string(mode) service := container.Config.PublishService networkName := mode.NetworkName() if !networkByName && mode.IsDefault() { if service != "" { service, networkName, networkDriver = parseService(controller, service) } else { networkName = controller.Config().Daemon.DefaultNetwork networkDriver = controller.Config().Daemon.DefaultDriver } } else if service != "" { return fmt.Errorf("conflicting options: publishing a service and network mode") } if runconfig.NetworkMode(networkDriver).IsBridge() && container.daemon.config.DisableBridge { container.Config.NetworkDisabled = true return nil } if service == "" { // dot character "." has a special meaning to support SERVICE[.NETWORK] format. // For backward compatibility, replacing "." with "-", instead of failing service = strings.Replace(container.Name, ".", "-", -1) // Service names dont like "/" in them. removing it instead of failing for backward compatibility service = strings.Replace(service, "/", "", -1) } if !networkByName { n, err = controller.NetworkByName(networkName) } if container.secondaryNetworkRequired(networkDriver) { // Configure Bridge as secondary network for port binding purposes if err := container.configureNetwork("bridge", service, "bridge", false); err != nil { return err } } if err := container.configureNetwork(networkName, service, networkDriver, mode.IsDefault()); err != nil { return err } return container.WriteHostConfig() }
func Convert(c *project.ServiceConfig) (*runconfig.Config, *runconfig.HostConfig, error) { vs := Filter(c.Volumes, isVolume) volumes := make(map[string]struct{}, len(vs)) for _, v := range vs { volumes[v] = struct{}{} } cmd, _ := shlex.Split(c.Command) entrypoint, _ := shlex.Split(c.Entrypoint) ports, binding, err := nat.ParsePortSpecs(c.Ports) if err != nil { return nil, nil, err } restart, err := runconfig.ParseRestartPolicy(c.Restart) if err != nil { return nil, nil, err } dns := c.Dns.Slice() dnssearch := c.DnsSearch.Slice() labels := c.Labels.MapParts() if len(c.Expose) > 0 { exposedPorts, _, err := nat.ParsePortSpecs(c.Expose) ports = exposedPorts if err != nil { return nil, nil, err } } config := &runconfig.Config{ Entrypoint: runconfig.NewEntrypoint(entrypoint...), Hostname: c.Hostname, Domainname: c.DomainName, User: c.User, Env: c.Environment.Slice(), Cmd: runconfig.NewCommand(cmd...), Image: c.Image, Labels: labels, ExposedPorts: ports, Tty: c.Tty, OpenStdin: c.StdinOpen, WorkingDir: c.WorkingDir, Volumes: volumes, } host_config := &runconfig.HostConfig{ VolumesFrom: c.VolumesFrom, CapAdd: c.CapAdd, CapDrop: c.CapDrop, CpuShares: c.CpuShares, Privileged: c.Privileged, Binds: Filter(c.Volumes, isBind), Dns: dns, DnsSearch: dnssearch, LogConfig: runconfig.LogConfig{ Type: c.LogDriver, }, Memory: c.MemLimit, NetworkMode: runconfig.NetworkMode(c.Net), ReadonlyRootfs: c.ReadOnly, PidMode: runconfig.PidMode(c.Pid), IpcMode: runconfig.IpcMode(c.Ipc), PortBindings: binding, RestartPolicy: restart, } return config, host_config, nil }
func (container *Container) connectToNetwork(idOrName string, updateSettings bool) error { if container.hostConfig.NetworkMode.IsContainer() { return runconfig.ErrConflictSharedNetwork } if runconfig.NetworkMode(idOrName).IsBridge() && container.daemon.configStore.DisableBridge { container.Config.NetworkDisabled = true return nil } controller := container.daemon.netController n, err := container.daemon.FindNetwork(idOrName) if err != nil { return err } if updateSettings { if err := container.updateNetworkSettings(n); err != nil { return err } } ep, err := container.getEndpointInNetwork(n) if err != nil { if _, ok := err.(libnetwork.ErrNoSuchEndpoint); !ok { return err } createOptions, err := container.buildCreateEndpointOptions() if err != nil { return err } endpointName := strings.TrimPrefix(container.Name, "/") ep, err = n.CreateEndpoint(endpointName, createOptions...) if err != nil { return err } } if err := container.updateEndpointNetworkSettings(n, ep); err != nil { return err } var sb libnetwork.Sandbox controller.WalkSandboxes(func(s libnetwork.Sandbox) bool { if s.ContainerID() == container.ID { sb = s return true } return false }) if sb == nil { options, err := container.buildSandboxOptions(n) if err != nil { return err } sb, err = controller.NewSandbox(container.ID, options...) if err != nil { return err } } container.updateSandboxNetworkSettings(sb) if err := ep.Join(sb); err != nil { return err } if err := container.updateJoinInfo(ep); err != nil { return derr.ErrorCodeJoinInfo.WithArgs(err) } return nil }