Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reservations to admin control subnet allocs #369

Merged
merged 1 commit into from
Nov 17, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ func (n *Network) runOnce(extIface *backend.ExternalInterface, inited func(bn ba
defer wg.Wait()

dur := n.bn.Lease().Expiration.Sub(time.Now()) - renewMargin

for {
select {
case <-time.After(dur):
Expand All @@ -164,12 +163,16 @@ func (n *Network) runOnce(extIface *backend.ExternalInterface, inited func(bn ba
dur = n.bn.Lease().Expiration.Sub(time.Now()) - renewMargin

case e := <-evts:
if e.Type == subnet.EventRemoved {
switch e.Type {
case subnet.EventAdded:
n.bn.Lease().Expiration = e.Lease.Expiration
dur = n.bn.Lease().Expiration.Sub(time.Now()) - renewMargin

case subnet.EventRemoved:
log.Warning("Lease has been revoked")
interruptFunc()
return errInterrupted
}
dur = n.bn.Lease().Expiration.Sub(time.Now()) - renewMargin

case <-n.ctx.Done():
return errCanceled
Expand Down
57 changes: 57 additions & 0 deletions remote/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,63 @@ func (m *RemoteManager) WatchNetworks(ctx context.Context, cursor interface{}) (
return wr, nil
}

func (m *RemoteManager) AddReservation(ctx context.Context, network string, r *subnet.Reservation) error {
url := m.mkurl(network, "reservations")

body, err := json.Marshal(r)
if err != nil {
return err
}

resp, err := m.httpVerb(ctx, "POST", url, "application/json", body)
if err != nil {
return err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return httpError(resp)
}
return nil
}

func (m *RemoteManager) RemoveReservation(ctx context.Context, network string, sn ip.IP4Net) error {
url := m.mkurl(network, "reservations", subnet.MakeSubnetKey(sn))

resp, err := m.httpVerb(ctx, "DELETE", url, "", nil)
if err != nil {
return err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return httpError(resp)
}

return nil
}

func (m *RemoteManager) ListReservations(ctx context.Context, network string) ([]subnet.Reservation, error) {
url := m.mkurl(network, "reservations")

resp, err := m.httpVerb(ctx, "GET", url, "", nil)
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return nil, httpError(resp)
}

rs := []subnet.Reservation{}
if err := json.NewDecoder(resp.Body).Decode(&rs); err != nil {
return nil, err
}

return rs, nil
}

func httpError(resp *http.Response) error {
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
Expand Down
82 changes: 66 additions & 16 deletions remote/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ func jsonResponse(w http.ResponseWriter, code int, v interface{}) {

// GET /{network}/config
func handleGetNetworkConfig(ctx context.Context, sm subnet.Manager, w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()

network := mux.Vars(r)["network"]
if network == "_" {
network = ""
Expand All @@ -65,8 +63,6 @@ func handleGetNetworkConfig(ctx context.Context, sm subnet.Manager, w http.Respo

// POST /{network}/leases
func handleAcquireLease(ctx context.Context, sm subnet.Manager, w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()

network := mux.Vars(r)["network"]
if network == "_" {
network = ""
Expand All @@ -91,8 +87,6 @@ func handleAcquireLease(ctx context.Context, sm subnet.Manager, w http.ResponseW

// PUT /{network}/{lease.network}
func handleRenewLease(ctx context.Context, sm subnet.Manager, w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()

network := mux.Vars(r)["network"]
if network == "_" {
network = ""
Expand All @@ -115,8 +109,6 @@ func handleRenewLease(ctx context.Context, sm subnet.Manager, w http.ResponseWri
}

func handleRevokeLease(ctx context.Context, sm subnet.Manager, w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()

network := mux.Vars(r)["network"]
if network == "_" {
network = ""
Expand All @@ -134,8 +126,6 @@ func handleRevokeLease(ctx context.Context, sm subnet.Manager, w http.ResponseWr
fmt.Fprint(w, err)
return
}

w.WriteHeader(http.StatusOK)
}

func getCursor(u *url.URL) interface{} {
Expand All @@ -148,8 +138,6 @@ func getCursor(u *url.URL) interface{} {

// GET /{network}/leases/subnet?next=cursor
func handleWatchLease(ctx context.Context, sm subnet.Manager, w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()

network := mux.Vars(r)["network"]
if network == "_" {
network = ""
Expand Down Expand Up @@ -186,8 +174,6 @@ func handleWatchLease(ctx context.Context, sm subnet.Manager, w http.ResponseWri

// GET /{network}/leases?next=cursor
func handleWatchLeases(ctx context.Context, sm subnet.Manager, w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()

network := mux.Vars(r)["network"]
if network == "_" {
network = ""
Expand Down Expand Up @@ -218,8 +204,6 @@ func handleWatchLeases(ctx context.Context, sm subnet.Manager, w http.ResponseWr
// GET /?next=cursor watches
// GET / retrieves all networks
func handleNetworks(ctx context.Context, sm subnet.Manager, w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()

cursor := getCursor(r.URL)
wr, err := sm.WatchNetworks(ctx, cursor)
if err != nil {
Expand All @@ -241,6 +225,67 @@ func handleNetworks(ctx context.Context, sm subnet.Manager, w http.ResponseWrite
jsonResponse(w, http.StatusOK, wr)
}

// POST /{network}/reservations
func handleAddReservation(ctx context.Context, sm subnet.Manager, w http.ResponseWriter, r *http.Request) {
network := mux.Vars(r)["network"]
if network == "_" {
network = ""
}

rsv := &subnet.Reservation{}
if err := json.NewDecoder(r.Body).Decode(rsv); err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(w, "JSON decoding error: ", err)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error string does not need to be json format?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's a good point. I'll file an issue to evaluate changing a API on how the errors are reported.

return
}

if err := sm.AddReservation(ctx, network, rsv); err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprint(w, fmt.Errorf("internal error: %v", err))
return
}
}

// DELETE /{network}/reservations/{subnet}
func handleRemoveReservation(ctx context.Context, sm subnet.Manager, w http.ResponseWriter, r *http.Request) {
network := mux.Vars(r)["network"]
if network == "_" {
network = ""
}

sn := subnet.ParseSubnetKey(mux.Vars(r)["subnet"])
if sn == nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(w, "bad subnet")
return
}

if err := sm.RemoveReservation(ctx, network, *sn); err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprint(w, err)
return
}

w.WriteHeader(http.StatusOK)
}

// GET /{network}/reservations
func handleListReservations(ctx context.Context, sm subnet.Manager, w http.ResponseWriter, r *http.Request) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also add a comment for this handler like the above for consistency?

network := mux.Vars(r)["network"]
if network == "_" {
network = ""
}

leases, err := sm.ListReservations(ctx, network)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprint(w, err)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should return right after 305, right?

return
}

jsonResponse(w, http.StatusOK, leases)
}

func bindHandler(h handler, ctx context.Context, sm subnet.Manager) http.HandlerFunc {
return func(resp http.ResponseWriter, req *http.Request) {
h(ctx, sm, resp, req)
Expand Down Expand Up @@ -323,13 +368,18 @@ func RunServer(ctx context.Context, sm subnet.Manager, listenAddr, cafile, certf

r := mux.NewRouter()
r.HandleFunc("/v1/{network}/config", bindHandler(handleGetNetworkConfig, ctx, sm)).Methods("GET")

r.HandleFunc("/v1/{network}/leases", bindHandler(handleAcquireLease, ctx, sm)).Methods("POST")
r.HandleFunc("/v1/{network}/leases/{subnet}", bindHandler(handleWatchLease, ctx, sm)).Methods("GET")
r.HandleFunc("/v1/{network}/leases/{subnet}", bindHandler(handleRenewLease, ctx, sm)).Methods("PUT")
r.HandleFunc("/v1/{network}/leases/{subnet}", bindHandler(handleRevokeLease, ctx, sm)).Methods("DELETE")
r.HandleFunc("/v1/{network}/leases", bindHandler(handleWatchLeases, ctx, sm)).Methods("GET")
r.HandleFunc("/v1/", bindHandler(handleNetworks, ctx, sm)).Methods("GET")

r.HandleFunc("/v1/{network}/reservations", bindHandler(handleListReservations, ctx, sm)).Methods("GET")
r.HandleFunc("/v1/{network}/reservations", bindHandler(handleAddReservation, ctx, sm)).Methods("POST")
r.HandleFunc("/v1/{network}/reservations/{subnet}", bindHandler(handleRemoveReservation, ctx, sm)).Methods("DELETE")

l, err := listener(listenAddr, cafile, certfile, keyfile)
if err != nil {
log.Errorf("Error listening on %v: %v", listenAddr, err)
Expand Down
Loading