Esempio n. 1
0
func (alloc *Allocator) handleHTTPAllocate(dockerCli *docker.Client, w http.ResponseWriter, ident string, checkAlive bool, subnet address.CIDR) {
	closedChan := w.(http.CloseNotifier).CloseNotify()
	addr, err := alloc.Allocate(ident, subnet.HostRange(),
		func() bool {
			select {
			case <-closedChan:
				return true
			default:
				res := checkAlive && dockerCli != nil && dockerCli.IsContainerNotRunning(ident)
				checkAlive = false // we check only once; if the container dies later we learn about that through events
				return res
			}
		})
	if err != nil {
		if _, ok := err.(*errorCancelled); ok { // cancellation is not really an error
			common.Log.Infoln("[allocator]:", err.Error())
			fmt.Fprint(w, "cancelled")
			return
		}
		badRequest(w, err)
		return
	}

	fmt.Fprintf(w, "%s/%d", addr, subnet.PrefixLen)
}
Esempio n. 2
0
File: http.go Progetto: n054/weave
func hasBeenCancelled(dockerCli *docker.Client, closedChan <-chan bool, ident string, checkAlive bool) func() bool {
	return func() bool {
		select {
		case <-closedChan:
			return true
		default:
			res := checkAlive && dockerCli != nil && dockerCli.IsContainerNotRunning(ident)
			checkAlive = false // we check only once; if the container dies later we learn about that through events
			return res
		}
	}
}
Esempio n. 3
0
File: http.go Progetto: binhnv/weave
func (alloc *Allocator) handleHTTPAllocate(dockerCli *docker.Client, w http.ResponseWriter, ident string, checkAlive bool, subnet address.CIDR) {
	closedChan := w.(http.CloseNotifier).CloseNotify()
	addr, err := alloc.Allocate(ident, subnet.HostRange(), closedChan)
	if err != nil {
		if _, ok := err.(*errorCancelled); ok { // cancellation is not really an error
			common.Log.Infoln("[allocator]:", err.Error())
			fmt.Fprint(w, "cancelled")
			return
		}
		badRequest(w, err)
		return
	}
	if checkAlive && dockerCli != nil && dockerCli.IsContainerNotRunning(ident) {
		common.Log.Infof("[allocator] '%s' is not running: freeing %s", ident, addr)
		alloc.Free(ident, addr)
		fmt.Fprint(w, "cancelled")
		return
	}

	fmt.Fprintf(w, "%s/%d", addr, subnet.PrefixLen)
}
Esempio n. 4
0
File: http.go Progetto: gnomix/weave
// HandleHTTP wires up ipams HTTP endpoints to the provided mux.
func (alloc *Allocator) HandleHTTP(router *mux.Router, defaultSubnet address.CIDR, dockerCli *docker.Client) {
	router.Methods("PUT").Path("/ip/{id}/{ip}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		closedChan := w.(http.CloseNotifier).CloseNotify()
		vars := mux.Vars(r)
		ident := vars["id"]
		ipStr := vars["ip"]
		if ip, err := address.ParseIP(ipStr); err != nil {
			badRequest(w, err)
			return
		} else if err := alloc.Claim(ident, ip, closedChan); err != nil {
			badRequest(w, fmt.Errorf("Unable to claim: %s", err))
			return
		}

		w.WriteHeader(204)
	})

	router.Methods("GET").Path("/ip/{id}/{ip}/{prefixlen}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		cidr := vars["ip"] + "/" + vars["prefixlen"]
		_, subnet, err := address.ParseCIDR(cidr)
		if err != nil {
			badRequest(w, err)
			return
		}
		addr, err := alloc.Lookup(vars["id"], subnet.HostRange())
		if err != nil {
			http.NotFound(w, r)
			return
		}
		fmt.Fprintf(w, "%s/%d", addr, subnet.PrefixLen)
	})

	router.Methods("GET").Path("/ip/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		addr, err := alloc.Lookup(mux.Vars(r)["id"], defaultSubnet.HostRange())
		if err != nil {
			http.NotFound(w, r)
			return
		}
		fmt.Fprintf(w, "%s/%d", addr, defaultSubnet.PrefixLen)
	})

	router.Methods("POST").Path("/ip/{id}/{ip}/{prefixlen}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		closedChan := w.(http.CloseNotifier).CloseNotify()
		vars := mux.Vars(r)
		ident := vars["id"]
		cidrStr := vars["ip"] + "/" + vars["prefixlen"]
		subnetAddr, cidr, err := address.ParseCIDR(cidrStr)
		if err != nil {
			badRequest(w, err)
			return
		}
		if cidr.Start != subnetAddr {
			badRequest(w, fmt.Errorf("Invalid subnet %s - bits after network prefix are not all zero", cidrStr))
			return
		}
		addr, err := alloc.Allocate(ident, cidr.HostRange(), closedChan)
		if err != nil {
			badRequest(w, fmt.Errorf("Unable to allocate: %s", err))
			return
		}
		if dockerCli != nil && dockerCli.IsContainerNotRunning(ident) {
			common.Log.Infof("[allocator] '%s' is not running: freeing %s", ident, addr)
			alloc.Free(ident, addr)
			return
		}

		fmt.Fprintf(w, "%s/%d", addr, cidr.PrefixLen)
	})

	router.Methods("POST").Path("/ip/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		closedChan := w.(http.CloseNotifier).CloseNotify()
		ident := mux.Vars(r)["id"]
		newAddr, err := alloc.Allocate(ident, defaultSubnet.HostRange(), closedChan)
		if err != nil {
			badRequest(w, err)
			return
		}
		if dockerCli != nil && dockerCli.IsContainerNotRunning(ident) {
			common.Log.Infof("[allocator] '%s' is not running: freeing %s", ident, newAddr)
			alloc.Free(ident, newAddr)
			return
		}

		fmt.Fprintf(w, "%s/%d", newAddr, defaultSubnet.PrefixLen)
	})

	router.Methods("DELETE").Path("/ip/{id}/{ip}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		ident := vars["id"]
		ipStr := vars["ip"]
		if ip, err := address.ParseIP(ipStr); err != nil {
			badRequest(w, err)
			return
		} else if err := alloc.Free(ident, ip); err != nil {
			badRequest(w, fmt.Errorf("Unable to free: %s", err))
			return
		}

		w.WriteHeader(204)
	})

	router.Methods("DELETE").Path("/ip/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ident := mux.Vars(r)["id"]
		if err := alloc.Delete(ident); err != nil {
			badRequest(w, err)
			return
		}

		w.WriteHeader(204)
	})

	router.Methods("DELETE").Path("/peer").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		alloc.Shutdown()
		w.WriteHeader(204)
	})

	router.Methods("DELETE").Path("/peer/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		ident := mux.Vars(r)["id"]
		if err := alloc.AdminTakeoverRanges(ident); err != nil {
			badRequest(w, err)
			return
		}

		w.WriteHeader(204)
	})
}
Esempio n. 5
0
func (n *Nameserver) HandleHTTP(router *mux.Router, dockerCli *docker.Client) {
	router.Methods("GET").Path("/domain").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, n.domain)
	})

	router.Methods("PUT").Path("/name/{container}/{ip}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var (
			vars      = mux.Vars(r)
			container = vars["container"]
			ipStr     = vars["ip"]
			hostname  = dns.Fqdn(r.FormValue("fqdn"))
			ip, err   = address.ParseIP(ipStr)
		)
		if err != nil {
			n.badRequest(w, err)
			return
		}

		if err := n.AddEntry(hostname, container, n.ourName, ip); err != nil {
			n.badRequest(w, fmt.Errorf("Unable to add entry: %v", err))
			return
		}

		if r.FormValue("check-alive") == "true" && dockerCli != nil && dockerCli.IsContainerNotRunning(container) {
			n.infof("container '%s' is not running: removing", container)
			if err := n.Delete(hostname, container, ipStr, ip); err != nil {
				n.infof("failed to remove: %v", err)
			}
		}

		w.WriteHeader(204)
	})

	deleteHandler := func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)

		hostname := r.FormValue("fqdn")
		if hostname == "" {
			hostname = "*"
		} else {
			hostname = dns.Fqdn(hostname)
		}

		container, ok := vars["container"]
		if !ok {
			container = "*"
		}

		ipStr, ok := vars["ip"]
		ip, err := address.ParseIP(ipStr)
		if ok && err != nil {
			n.badRequest(w, err)
			return
		} else if !ok {
			ipStr = "*"
		}

		if err := n.Delete(hostname, container, ipStr, ip); err != nil {
			n.badRequest(w, fmt.Errorf("Unable to delete entries: %v", err))
			return
		}
		w.WriteHeader(204)
	}
	router.Methods("DELETE").Path("/name/{container}/{ip}").HandlerFunc(deleteHandler)
	router.Methods("DELETE").Path("/name/{container}").HandlerFunc(deleteHandler)
	router.Methods("DELETE").Path("/name").HandlerFunc(deleteHandler)

	router.Methods("GET").Path("/name").Headers("Accept", "application/json").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		n.RLock()
		defer n.RUnlock()
		if err := json.NewEncoder(w).Encode(n.entries); err != nil {
			n.badRequest(w, fmt.Errorf("Error marshalling response: %v", err))
		}
	})
}
Esempio n. 6
0
func ServeHTTP(listener net.Listener, version string, server *DNSServer, dockerCli *docker.Client) {

	muxRouter := mux.NewRouter()

	muxRouter.Methods("GET").Path("/status").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintln(w, "weave DNS", version)
		fmt.Fprintln(w, server.Status())
		fmt.Fprintln(w, server.Zone.Status())
	})

	muxRouter.Methods("GET").Path("/domain").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, server.Zone.Domain())
	})

	muxRouter.Methods("PUT").Path("/name/{id:.+}/{ip:.+}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		reqError := func(msg string, logmsg string, logargs ...interface{}) {
			httpErrorAndLog(Warning, w, msg, http.StatusBadRequest, logmsg, logargs...)
		}

		vars := mux.Vars(r)
		idStr := vars["id"]
		ipStr := vars["ip"]
		name := r.FormValue("fqdn")

		if name == "" {
			reqError("Invalid FQDN", "Invalid FQDN in request: %s, %s", r.URL, r.Form)
			return
		}

		ip := net.ParseIP(ipStr)
		if ip == nil {
			reqError("Invalid IP", "Invalid IP in request: %s", ipStr)
			return
		}

		domain := server.Zone.Domain()
		if !dns.IsSubDomain(domain, name) {
			Info.Printf("[http] Ignoring name %s, not in %s", name, domain)
			return
		}
		Info.Printf("[http] Adding %s -> %s", name, ipStr)
		if err := server.Zone.AddRecord(idStr, name, ip); err != nil {
			if _, ok := err.(DuplicateError); !ok {
				httpErrorAndLog(
					Error, w, "Internal error", http.StatusInternalServerError,
					"Unexpected error from DB: %s", err)
				return
			} // oh, I already know this. whatever.
		}

		if dockerCli != nil && dockerCli.IsContainerNotRunning(idStr) {
			Info.Printf("[http] '%s' is not running: removing", idStr)
			server.Zone.DeleteRecords(idStr, name, ip)
		}
	})

	muxRouter.Methods("DELETE").Path("/name/{id:.+}/{ip:.+}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		idStr := vars["id"]
		ipStr := vars["ip"]

		ip := net.ParseIP(ipStr)
		if ip == nil {
			httpErrorAndLog(
				Warning, w, "Invalid IP in request", http.StatusBadRequest,
				"Invalid IP in request: %s", ipStr)
			return
		}

		fqdnStr, fqdn := extractFQDN(r)

		Info.Printf("[http] Deleting ID %s, IP %s, FQDN %s", idStr, ipStr, fqdnStr)
		server.Zone.DeleteRecords(idStr, fqdn, ip)
	})

	muxRouter.Methods("DELETE").Path("/name/{id:.+}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		idStr := vars["id"]

		fqdnStr, fqdn := extractFQDN(r)

		Info.Printf("[http] Deleting ID %s, IP *, FQDN %s", idStr, fqdnStr)
		server.Zone.DeleteRecords(idStr, fqdn, net.IP{})
	})

	muxRouter.Methods("DELETE").Path("/name").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		fqdnStr, fqdn := extractFQDN(r)

		Info.Printf("[http] Deleting ID *, IP *, FQDN %s", fqdnStr)
		server.Zone.DeleteRecords("", fqdn, net.IP{})
	})

	http.Handle("/", muxRouter)

	if err := http.Serve(listener, nil); err != nil {
		Error.Fatal("[http] Unable to serve http: ", err)
	}
}