forked from rook/rook
160 lines
3.9 KiB
Go
160 lines
3.9 KiB
Go
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
|
|
ceph "github.com/quantum/castle/pkg/cephmgr/client"
|
|
"github.com/quantum/castle/pkg/model"
|
|
)
|
|
|
|
// Gets the images that have been created in this cluster.
|
|
// GET
|
|
// /image
|
|
func (h *Handler) GetImages(w http.ResponseWriter, r *http.Request) {
|
|
adminConn, ok := h.handleConnectToCeph(w)
|
|
if !ok {
|
|
return
|
|
}
|
|
defer adminConn.Shutdown()
|
|
|
|
// first list all the pools so that we can retrieve images from all pools
|
|
pools, err := ceph.ListPoolSummaries(adminConn)
|
|
if err != nil {
|
|
log.Printf("failed to list pools: %+v", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
result := []model.BlockImage{}
|
|
|
|
// for each pool, open an IO context to get further details about all the images in the pool
|
|
for _, p := range pools {
|
|
ioctx, ok := handleOpenIOContext(w, adminConn, p.Name)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
// get all the image names for the current pool
|
|
imageNames, err := ioctx.GetImageNames()
|
|
if err != nil {
|
|
log.Printf("failed to get image names from pool %s: %+v", p.Name, err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// for each image name, open the image and stat it for further details
|
|
images := make([]model.BlockImage, len(imageNames))
|
|
for i, name := range imageNames {
|
|
image := ioctx.GetImage(name)
|
|
image.Open(true)
|
|
defer image.Close()
|
|
imageStat, err := image.Stat()
|
|
if err != nil {
|
|
log.Printf("failed to stat image %s from pool %s: %+v", name, p.Name, err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// add the current image's details to the result set
|
|
images[i] = model.BlockImage{
|
|
Name: name,
|
|
PoolName: p.Name,
|
|
Size: imageStat.Size,
|
|
}
|
|
}
|
|
|
|
result = append(result, images...)
|
|
}
|
|
|
|
FormatJsonResponse(w, result)
|
|
}
|
|
|
|
// Creates a new image in this cluster.
|
|
// POST
|
|
// /image
|
|
func (h *Handler) CreateImage(w http.ResponseWriter, r *http.Request) {
|
|
var newImage model.BlockImage
|
|
body, ok := handleReadBody(w, r, "create image")
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
if err := json.Unmarshal(body, &newImage); err != nil {
|
|
log.Printf("failed to unmarshal create image request body '%s': %+v", string(body), err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if newImage.Name == "" || newImage.PoolName == "" || newImage.Size == 0 {
|
|
log.Printf("image missing required fields: %+v", newImage)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
adminConn, ok := h.handleConnectToCeph(w)
|
|
if !ok {
|
|
return
|
|
}
|
|
defer adminConn.Shutdown()
|
|
|
|
ioctx, ok := handleOpenIOContext(w, adminConn, newImage.PoolName)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
createdImage, err := ioctx.CreateImage(newImage.Name, newImage.Size, 22)
|
|
if err != nil {
|
|
log.Printf("failed to create image %+v: %+v", newImage, err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Write([]byte(fmt.Sprintf("succeeded created image %s", createdImage.Name())))
|
|
}
|
|
|
|
// Gets information needed to map an image to a local device
|
|
// GET
|
|
// /image/mapinfo
|
|
func (h *Handler) GetImageMapInfo(w http.ResponseWriter, r *http.Request) {
|
|
// TODO: auth is extremely important here because we are returning cephx credentials
|
|
|
|
adminConn, ok := h.handleConnectToCeph(w)
|
|
if !ok {
|
|
return
|
|
}
|
|
defer adminConn.Shutdown()
|
|
|
|
monStatus, err := ceph.GetMonStatus(adminConn)
|
|
if err != nil {
|
|
log.Printf("failed to get monitor status, err: %+v", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// TODO: don't always return admin creds
|
|
entity := "client.admin"
|
|
user := "admin"
|
|
secret, err := ceph.AuthGetKey(adminConn, entity)
|
|
if err != nil {
|
|
log.Printf("failed to get key for %s: %+v", entity, err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
monAddrs := make([]string, len(monStatus.MonMap.Mons))
|
|
for i, m := range monStatus.MonMap.Mons {
|
|
monAddrs[i] = m.Address
|
|
}
|
|
|
|
mapInfo := model.BlockImageMapInfo{
|
|
MonAddresses: monAddrs,
|
|
UserName: user,
|
|
SecretKey: secret,
|
|
}
|
|
|
|
FormatJsonResponse(w, mapInfo)
|
|
}
|