// Allocate an external port and map it to the interface func AllocatePort(job *engine.Job) engine.Status { var ( err error ip = defaultBindingIP id = job.Args[0] hostIP = job.Getenv("HostIP") hostPort = job.GetenvInt("HostPort") containerPort = job.GetenvInt("ContainerPort") proto = job.Getenv("Proto") network = currentInterfaces[id] ) if hostIP != "" { ip = net.ParseIP(hostIP) } // host ip, proto, and host port hostPort, err = portallocator.RequestPort(ip, proto, hostPort) if err != nil { job.Error(err) return engine.StatusErr } var ( container net.Addr host net.Addr ) if proto == "tcp" { host = &net.TCPAddr{IP: ip, Port: hostPort} container = &net.TCPAddr{IP: network.IP, Port: containerPort} } else { host = &net.UDPAddr{IP: ip, Port: hostPort} container = &net.UDPAddr{IP: network.IP, Port: containerPort} } if err := portmapper.Map(container, ip, hostPort); err != nil { portallocator.ReleasePort(ip, proto, hostPort) job.Error(err) return engine.StatusErr } network.PortMappings = append(network.PortMappings, host) out := engine.Env{} out.Set("HostIP", ip.String()) out.SetInt("HostPort", hostPort) if _, err := out.WriteTo(job.Stdout); err != nil { job.Error(err) return engine.StatusErr } return engine.StatusOK }
// release an interface for a select ip func Release(job *engine.Job) engine.Status { var ( id = job.Args[0] containerInterface = currentInterfaces[id] ip net.IP port int proto string ) for _, nat := range containerInterface.PortMappings { if err := portmapper.Unmap(nat); err != nil { log.Printf("Unable to unmap port %s: %s", nat, err) } // this is host mappings switch a := nat.(type) { case *net.TCPAddr: proto = "tcp" ip = a.IP port = a.Port case *net.UDPAddr: proto = "udp" ip = a.IP port = a.Port } if err := portallocator.ReleasePort(ip, proto, port); err != nil { log.Printf("Unable to release port %s", nat) } } if err := ipallocator.ReleaseIP(bridgeNetwork, &containerInterface.IP); err != nil { log.Printf("Unable to release ip %s\n", err) } return engine.StatusOK }