Skip to content

Commit

Permalink
Fetch current OSD pool configuration over the API (#409)
Browse files Browse the repository at this point in the history
  • Loading branch information
masnax authored Sep 12, 2024
1 parent 54cf522 commit ef42f09
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 3 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,13 @@ jobs:
sudo microceph.ceph osd pool create mypool
sudo microceph pool set-rf --size 1 ""
sudo microceph.ceph config get osd.1 osd_pool_default_size | fgrep -x "1"
sudo microceph pool list | fgrep "mypool" | fgrep -q " 3 "
sudo microceph pool set-rf --size 3 mypool
sudo microceph.ceph osd pool get mypool size | fgrep -x "size: 3"
sudo microceph pool list | fgrep "mypool" | fgrep -q " 3 "
sudo microceph pool set-rf --size 1 "*"
sudo microceph.ceph osd pool get mypool size | fgrep -x "size: 1"
sudo microceph pool list | fgrep "mypool" | fgrep -q " 1 "
- name: Test log operations
run: |
Expand Down
20 changes: 19 additions & 1 deletion microceph/api/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,29 @@ import (
)

// /1.0/pools-op endpoint.
var poolsCmd = rest.Endpoint{
var poolsOpCmd = rest.Endpoint{
Path: "pools-op",
Put: rest.EndpointAction{Handler: cmdPoolsPut, ProxyTarget: true},
}

// /1.0/pools endpoint.
var poolsCmd = rest.Endpoint{
Path: "pools",
Get: rest.EndpointAction{Handler: cmdPoolsGet, ProxyTarget: true},
}

func cmdPoolsGet(s state.State, r *http.Request) response.Response {
logger.Debug("cmdPoolGet")
pools, err := ceph.GetOSDPools()
if err != nil {
return response.SmartError(err)
}

logger.Debug("cmdPoolGet done")

return response.SyncResponse(true, pools)
}

func cmdPoolsPut(s state.State, r *http.Request) response.Response {
var req types.PoolPut

Expand Down
1 change: 1 addition & 0 deletions microceph/api/servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var Servers = map[string]rest.Server{
mdsServiceCmd,
mgrServiceCmd,
monServiceCmd,
poolsOpCmd,
poolsCmd,
clientCmd,
clientConfigsCmd,
Expand Down
9 changes: 9 additions & 0 deletions microceph/api/types/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,12 @@ type PoolPut struct {
Pools []string `json:"pools" yaml:"pools"`
Size int64 `json:"size" yaml:"size"`
}

// Pool represents information about an OSD pool.
type Pool struct {
Pool string `json:"pool" yaml:"pool"`
PoolID int64 `json:"pool_id" yaml:"pool_id"`
Size int64 `json:"size" yaml:"size"`
MinSize int64 `json:"min_size" yaml:"min_size"`
CrushRule string `json:"crush_rule" yaml:"crush_rule"`
}
40 changes: 38 additions & 2 deletions microceph/ceph/osd.go
Original file line number Diff line number Diff line change
Expand Up @@ -1096,19 +1096,23 @@ func SetReplicationFactor(pools []string, size int64) error {

if len(pools) == 1 && pools[0] == "*" {
// Apply setting to all existing pools.
out, err := processExec.RunCommand("ceph", "osd", "pool", "ls")
out, err := processExec.RunCommand("ceph", "osd", "pool", "ls", "--format", "json")
if err != nil {
return fmt.Errorf("failed to list pools: %w", err)
}

pools = strings.Split(out, "\n")
err = json.Unmarshal([]byte(out), &pools)
if err != nil {
return fmt.Errorf("Failed to parse OSD pool names: %w", err)
}
}

for _, pool := range pools {
pool = strings.TrimSpace(pool)
if pool == "" {
continue
}

_, err := processExec.RunCommand("ceph", "osd", "pool", "set", pool, "size", ssize, "--yes-i-really-mean-it")
if err != nil {
return fmt.Errorf("failed to set pool size for %s: %w", pool, err)
Expand All @@ -1117,3 +1121,35 @@ func SetReplicationFactor(pools []string, size int64) error {

return nil
}

// GetOSDPools returns a list of OSD Pools and their configurations.
func GetOSDPools() ([]types.Pool, error) {
out, err := processExec.RunCommand("ceph", "osd", "pool", "ls", "--format", "json")
if err != nil {
return nil, fmt.Errorf("failed to list pools: %w", err)
}

var poolNames []string
err = json.Unmarshal([]byte(out), &poolNames)
if err != nil {
return nil, fmt.Errorf("Failed to parse OSD pool names: %w", err)
}

pools := make([]types.Pool, 0, len(poolNames))
for _, name := range poolNames {
out, err := processExec.RunCommand("ceph", "osd", "pool", "get", name, "all", "--format", "json")
if err != nil {
return nil, fmt.Errorf("Failed to fetch configuration for OSD pool %q: %w", name, err)
}

var pool types.Pool
err = json.Unmarshal([]byte(out), &pool)
if err != nil {
return nil, fmt.Errorf("Failed to parse %q OSD pool configuration: %w", name, err)
}

pools = append(pools, pool)
}

return pools, nil
}
14 changes: 14 additions & 0 deletions microceph/client/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,17 @@ func PoolSetReplicationFactor(ctx context.Context, c *microCli.Client, data *typ

return nil
}

func GetPools(ctx context.Context, c *microCli.Client) ([]types.Pool, error) {
queryCtx, cancel := context.WithTimeout(ctx, time.Second*120)
defer cancel()

var pools []types.Pool
err := c.Query(queryCtx, "GET", types.ExtendedPathPrefix, api.NewURL().Path("pools"), nil, &pools)
if err != nil {
return nil, fmt.Errorf("Failed to fetch OSD pools: %w", err)
}

return pools, nil

}
54 changes: 54 additions & 0 deletions microceph/cmd/microceph/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ package main

import (
"context"
"sort"
"strconv"

"github.com/spf13/cobra"

lxdCmd "github.com/canonical/lxd/shared/cmd"
"github.com/canonical/microceph/microceph/api/types"
"github.com/canonical/microceph/microceph/client"
"github.com/canonical/microcluster/v2/microcluster"
Expand Down Expand Up @@ -61,6 +64,53 @@ func (c *cmdPoolSetRF) Run(cmd *cobra.Command, args []string) error {
return client.PoolSetReplicationFactor(context.Background(), cli, req)
}

type cmdPoolList struct {
common *CmdControl
}

func (c *cmdPoolList) Command() *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "List information about OSD pools",
RunE: c.Run,
}

return cmd
}

func (c *cmdPoolList) Run(cmd *cobra.Command, args []string) error {
if len(args) != 0 {
return cmd.Help()
}

m, err := microcluster.App(microcluster.Args{StateDir: c.common.FlagStateDir})
if err != nil {
return err
}

cli, err := m.LocalClient()
if err != nil {
return err
}

pools, err := client.GetPools(cmd.Context(), cli)
if err != nil {
return err
}

data := make([][]string, len(pools))
for i, pool := range pools {
data[i] = []string{pool.Pool, strconv.Itoa(int(pool.Size)), pool.CrushRule}
}

header := []string{"NAME", "SIZE", "CRUSH RULE"}
sort.Sort(lxdCmd.SortColumnsNaturally(data))

return lxdCmd.RenderTable(lxdCmd.TableFormatTable, header, data, pools)

}

func (c *cmdPool) Command() *cobra.Command {
cmd := &cobra.Command{
Use: "pool",
Expand All @@ -71,6 +121,10 @@ func (c *cmdPool) Command() *cobra.Command {
poolSetRFCmd := cmdPoolSetRF{common: c.common, poolRF: c}
cmd.AddCommand(poolSetRFCmd.Command())

// list.
poolListCmd := cmdPoolList{common: c.common}
cmd.AddCommand(poolListCmd.Command())

// Workaround for subcommand usage errors. See: https://github.com/spf13/cobra/issues/706
cmd.Args = cobra.NoArgs
cmd.Run = func(cmd *cobra.Command, args []string) { _ = cmd.Usage() }
Expand Down

0 comments on commit ef42f09

Please sign in to comment.