Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
http.go 4.58 KiB
package nucleus

import (
	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
	"context"
	"fmt"
	"github.com/google/uuid"
	gpb "github.com/openconfig/gnmi/proto/gnmi"
	log "github.com/sirupsen/logrus"
	"net/http"
	"net/url"
	"time"
)

func stopHttpServer() error {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	log.Info("shutting down http server")
	return c.httpServer.Shutdown(ctx)
}

func registerHttpHandler(){
	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recovered in f", r)
		}
	}()
	http.HandleFunc("/api", httpHandler)
	http.HandleFunc("/livez", healthCheck)
	http.HandleFunc("/readyz", readynessCheck)
}

// deprecated
func httpApi() (err error) {
	registerHttpHandler()
	c.httpServer = &http.Server{Addr: ":8080"}

	go func() {
		err = c.httpServer.ListenAndServe()
		if err != nil {
			return
		}
	}()
	return nil
}

func healthCheck(writer http.ResponseWriter, request *http.Request) {
	writer.WriteHeader(http.StatusOK)
}

func readynessCheck(writer http.ResponseWriter, request *http.Request) {
	writer.WriteHeader(http.StatusOK)
}

// nolint
func httpHandler(writer http.ResponseWriter, request *http.Request) {
	log.WithFields(log.Fields{
		"request": request,
	}).Debug("incoming request")

	query, err := url.ParseQuery(request.URL.RawQuery)
	if err != nil {
		log.Error(err)
		writer.WriteHeader(http.StatusBadRequest)
		return
	}

	id, err := uuid.Parse(query.Get("uuid"))
	if err != nil {
		log.Error(err)
	}

	pid, err := uuid.Parse(query.Get("pnd"))
	if err != nil {
		log.Error(err)
	}

	sid, err := uuid.Parse(query.Get("sbi"))
	if err != nil {
		log.Error(err)
	}

	var pnd PrincipalNetworkDomain
	var sbi SouthboundInterface
	if query.Get("q") != "init" && query.Get("q") != "getIDs" {
		pnd, err = c.pndc.get(pid)
		if err != nil {
			log.Error(err)
			writer.WriteHeader(http.StatusInternalServerError)
			return
		}
		sbic := pnd.GetSBIs()
		sbi, err = sbic.(*sbiStore).get(sid)
		if err != nil {
			log.WithFields(log.Fields{
				"requested uuid": sid,
				"available uuids": sbic.(*sbiStore).UUIDs(),
			}).Error(err)
			writer.WriteHeader(http.StatusInternalServerError)
			return
		}
	}

	switch query.Get("q") {
	case "addDevice":
		d, err := NewDevice(sbi, &GnmiTransportOptions{
			Config: gnmi.Config{
				Addr:     query.Get("address"),
				Password: query.Get("password"),
				Username: query.Get("username"),
				Encoding: gpb.Encoding_JSON_IETF,
			},
			SetNode:   sbi.SetNode(),
			Unmarshal: sbi.(*OpenConfig).Unmarshal(),
			RespChan:  make(chan *gpb.SubscribeResponse),
		})
		err = pnd.AddDevice(d)
		if err != nil {
			writer.WriteHeader(http.StatusInternalServerError)
			log.Error(err)
			return
		}
		writer.WriteHeader(http.StatusCreated)
		fmt.Fprintf(writer, "device added\n")
		fmt.Fprintf(writer, "UUID: %v\n", d.Uuid)
	case "request":
		err = pnd.Request(id, query.Get("path"))
		if err != nil {
			switch err.(type) {
			case *ErrNotFound:
				writer.WriteHeader(http.StatusNotFound)
			default:
				writer.WriteHeader(http.StatusInternalServerError)
			}
			log.Error(err)
			return
		}
		writer.WriteHeader(http.StatusOK)
	case "requestAll":
		err = pnd.RequestAll(query.Get("path"))
		if err != nil {
			switch err.(type) {
			case *ErrNotFound:
				writer.WriteHeader(http.StatusNotFound)
			default:
				writer.WriteHeader(http.StatusInternalServerError)
			}
			log.Error(err)
			return
		}
		writer.WriteHeader(http.StatusOK)
	case "getDevice":
		device, err := pnd.MarshalDevice(id)
		if err != nil {
			switch err.(type) {
			case *ErrNotFound:
				writer.WriteHeader(http.StatusNotFound)
			default:
				writer.WriteHeader(http.StatusInternalServerError)
			}
			log.Error(err)
			return
		}
		writer.Header().Set("Content-Type", "application/json")
		fmt.Fprintf(writer, "%v", device)
	case "getIDs":
		writeIDs := func(typ string, ids []uuid.UUID) {
			fmt.Fprintf(writer, "%v:\n", typ)
			for i, id := range ids {
				fmt.Fprintf(writer, "%v: %v\n", i+1, id)
			}
		}
		writeIDs("PNDs", c.pndc.UUIDs())
		writeIDs("SBIs", c.sbic.UUIDs())
		if pnd != nil {
			writeIDs("Devices", pnd.(*pndImplementation).devices.UUIDs())
		}
	case "init":
		writeIDs := func(typ string, ids []uuid.UUID) {
			for _, id := range ids {
				fmt.Fprintf(writer, "%v", id)
			}
		}
		writeIDs("PNDs", c.pndc.UUIDs())
		writeIDs("SBIs", c.sbic.UUIDs())
	case "set":
		resp, err := pnd.(*pndImplementation).Set(id, query.Get("path"), query.Get("value"))
		if err != nil {
			writer.WriteHeader(http.StatusInternalServerError)
			log.Error(err)
			return
		}
		writer.WriteHeader(http.StatusOK)
		fmt.Fprintln(writer, resp)
	default:
		writer.WriteHeader(http.StatusBadRequest)
	}
}