Skip to content

Commit

Permalink
Add openstack resource manager support to API server (#196)
Browse files Browse the repository at this point in the history
* Add openstack resource manager support to API server. Openstack resource manager fetches compute units, users and projects data from Openstack's compute and identity API services.

* Mock compute and identity API servers have been added for e2e tests.

* A mix of SLURM and openstack tests are used in e2e tests to cover most of the scenarios. e2e test outputs have been updated.

* docs: Update config docs

---------

Signed-off-by: Mahendra Paipuri <[email protected]>
  • Loading branch information
mahendrapaipuri authored Oct 19, 2024
1 parent 8f4a855 commit 5d228bb
Show file tree
Hide file tree
Showing 42 changed files with 5,613 additions and 794 deletions.
4 changes: 2 additions & 2 deletions .promu-go-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ repository:
path: github.com/mahendrapaipuri/ceems
build:
binaries:
- name: mock_tsdb
path: ./cmd/mock_tsdb
- name: mock_servers
path: ./cmd/mock_servers
tags:
all: [osusergo, netgo, static_build]
flags: -a
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ ifeq ($(CGO_BUILD), 1)
PROMU_CONF ?= .promu-cgo.yml
pkgs := ./pkg/sqlite3 ./pkg/api/cli \
./pkg/api/db ./pkg/api/helper \
./pkg/api/resource ./pkg/api/resource/slurm \
./pkg/api/resource ./pkg/api/resource/slurm ./pkg/api/resource/openstack \
./pkg/api/updater \
./pkg/api/http ./cmd/ceems_api_server \
./pkg/lb/backend ./pkg/lb/cli \
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Installation instructions of CEEMS components can be found in
## Visualizing metrics with Grafana

CEEMS is meant to be used with Grafana for visualization and below are some of the
screenshots few possible metrics.
screenshots of dashboards.

### Time series compute unit CPU metrics

Expand Down
4 changes: 2 additions & 2 deletions cmd/ceems_api_server/main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package main

// We need to import each resource manager and updater package here.
import (
"log"
"os"

"github.com/mahendrapaipuri/ceems/pkg/api/cli"
// We need to import each resource manager package here to call init function.
_ "github.com/mahendrapaipuri/ceems/pkg/api/resource/openstack"
_ "github.com/mahendrapaipuri/ceems/pkg/api/resource/slurm"
// We need to import each updater package here to call init function.
_ "github.com/mahendrapaipuri/ceems/pkg/api/updater/tsdb"
)

Expand Down
169 changes: 162 additions & 7 deletions cmd/mock_tsdb/main.go → cmd/mock_servers/main.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
package main

import (
"context"
"encoding/json"
"fmt"
"hash/fnv"
"log"
"math"
"net/http"
"os"
"os/signal"
"regexp"
"slices"
"strconv"
"strings"
"syscall"
"time"

"github.com/mahendrapaipuri/ceems/pkg/tsdb"
)

// Default port Prometheus listens on.
const portNum string = ":9090"
// Default ports.
const (
promPortNum = ":9090"
osNovaPortNum = ":8080"
osKSPortNum = ":7070"
)

// Regex to capture query.
var (
Expand Down Expand Up @@ -211,25 +220,171 @@ func ConfigHandler(w http.ResponseWriter, r *http.Request) {
}
}

func main() {
// ServersHandler handles OS compute servers.
func ServersHandler(w http.ResponseWriter, r *http.Request) {
var fileName string
if _, ok := r.URL.Query()["deleted"]; ok {
fileName = "deleted"
} else {
fileName = "servers"
}

if data, err := os.ReadFile(fmt.Sprintf("pkg/api/testdata/openstack/compute/%s.json", fileName)); err == nil {
w.Write(data)

return
}

w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("KO"))
}

// UsersHandler handles OS users.
func UsersHandler(w http.ResponseWriter, r *http.Request) {
if data, err := os.ReadFile("pkg/api/testdata/openstack/identity/users.json"); err == nil {
w.Write(data)

return
}

w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("KO"))
}

// ProjectsHandler handles OS projects.
func ProjectsHandler(w http.ResponseWriter, r *http.Request) {
userID := r.PathValue("id")
if data, err := os.ReadFile(fmt.Sprintf("pkg/api/testdata/openstack/identity/%s.json", userID)); err == nil {
w.Write(data)

return
}

w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("KO"))
}

func promServer(ctx context.Context) {
log.Println("Starting fake prometheus server")

// Registering our handler functions, and creating paths.
http.HandleFunc("/api/v1/query", QueryHandler)
http.HandleFunc("/api/v1/status/config", ConfigHandler)
promMux := http.NewServeMux()
promMux.HandleFunc("/api/v1/query", QueryHandler)
promMux.HandleFunc("/api/v1/status/config", ConfigHandler)

log.Println("Started Prometheus on port", promPortNum)
log.Println("To close connection CTRL+C :-)")

// Start server
server := &http.Server{
Addr: promPortNum,
ReadHeaderTimeout: 3 * time.Second,
Handler: promMux,
}
defer func() {
if err := server.Shutdown(ctx); err != nil {
log.Println("Failed to shutdown fake Prometheus server", err)
}
}()

// Spinning up the server.
err := server.ListenAndServe()
if err != nil {
log.Fatal(err)
}
}

func osNovaServer(ctx context.Context) {
log.Println("Starting fake Openstack compute API server")

// Registering our handler functions, and creating paths.
osNovaMux := http.NewServeMux()
osNovaMux.HandleFunc("/v2.1/servers/detail", ServersHandler)

log.Println("Started on port", portNum)
log.Println("Started Openstack compute API server on port", osNovaPortNum)
log.Println("To close connection CTRL+C :-)")

// Start server
server := &http.Server{
Addr: portNum,
Addr: osNovaPortNum,
ReadHeaderTimeout: 3 * time.Second,
Handler: osNovaMux,
}
defer func() {
if err := server.Shutdown(ctx); err != nil {
log.Println("Failed to shutdown fake Openstack compute API server", err)
}
}()

// Spinning up the server.
err := server.ListenAndServe()
if err != nil {
log.Fatal(err)
}
}

func osKSServer(ctx context.Context) {
log.Println("Starting fake Openstack identity API server")

// Registering our handler functions, and creating paths.
osKSMux := http.NewServeMux()
osKSMux.HandleFunc("/v3/users", UsersHandler)
osKSMux.HandleFunc("/v3/users/{id}/projects", ProjectsHandler)

log.Println("Started Prometheus on port", osKSPortNum)
log.Println("To close connection CTRL+C :-)")

// Start server
server := &http.Server{
Addr: osKSPortNum,
ReadHeaderTimeout: 3 * time.Second,
Handler: osKSMux,
}
defer func() {
if err := server.Shutdown(ctx); err != nil {
log.Println("Failed to shutdown fake Openstack identity API server", err)
}
}()

// Spinning up the server.
err := server.ListenAndServe()
if err != nil {
log.Fatal(err)
}
}

func main() {
log.Println("Starting fake test servers")

args := os.Args[1:]

// Registering our handler functions, and creating paths.
ctx, cancel := context.WithCancel(context.Background())
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT)

if slices.Contains(args, "prom") {
go func() {
promServer(ctx)
}()
}

if slices.Contains(args, "os-compute") {
go func() {
osNovaServer(ctx)
}()
}

if slices.Contains(args, "os-identity") {
go func() {
osKSServer(ctx)
}()
}

sig := <-sigs
log.Println(sig)

cancel()

log.Println("Fake test servers have been stopped")
}
Loading

0 comments on commit 5d228bb

Please sign in to comment.