// Copyright (C) 2020 Marius Schellenberger package pve import ( "context" "errors" "fmt" "net/http" ) var ( ErrPoolExists = errors.New("pool already exists") ErrPoolNotExists = errors.New("pool does not exist") ErrEmptyPoolName = errors.New("pool name is empty") ) func MakePoolName(namespace, name string) string { return fmt.Sprintf("%s-%s", namespace, name) } type PoolClient struct { client *Client } func (c *PoolClient) exists(ctx context.Context, name string) (status int, err error) { req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/pools/%s", name), nil) if err != nil { return } resp, err := c.client.Do(req, nil) if err != nil { if !errors.Is(err, HTTPErr) { return } err = nil } status = resp.StatusCode return } func (c *PoolClient) Create(ctx context.Context, name string) (err error) { status, err := c.exists(ctx, name) if err != nil { return } if status == http.StatusOK { return ErrPoolExists } body := httpbody{"poolid": name} req, err := c.client.NewRequest(ctx, "POST", "/pools", body.Reader()) if err != nil { return } _, err = c.client.Do(req, nil) return } func (c *PoolClient) Delete(ctx context.Context, name string) (err error) { status, err := c.exists(ctx, name) if err != nil { return } if status != http.StatusOK { return ErrPoolNotExists } req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("/pools/%s", name), nil) if err != nil { return } _, err = c.client.Do(req, nil) return } type pools struct { PoolID string `json:"poolid"` } func (c *PoolClient) ListPools(ctx context.Context) (list []string, err error) { var ps []pools req, err := c.client.NewRequest(ctx, "GET", "/pools", nil) if err != nil { return } _, err = c.client.Do(req, &ps) if err != nil { return } for _, p := range ps { list = append(list, p.PoolID) } return } type poolMember struct { ID int `json:"vmid"` Name string `json:"name"` Node string `json:"node"` } type poolMembers []poolMember func (pms poolMembers) ServerList() (sl ServerRefList) { for _, pm := range pms { sl = append(sl, &ServerRef{ ID: pm.ID, Name: pm.Name, Node: pm.Node, }) } return } type pool struct { Members poolMembers `json:"members"` } func (c *PoolClient) ListMembers(ctx context.Context, name string) (sl ServerRefList, err error) { if name == "" { err = ErrEmptyPoolName return } var p pool req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("/pools/%s", name), nil) if err != nil { return } _, err = c.client.Do(req, &p) sl = p.Members.ServerList() return } func (c *PoolClient) FindServer(ctx context.Context, poolname, servername string, id int) (s *ServerRef, err error) { var pools []string if poolname != "" { pools = append(pools, poolname) } else { pools, err = c.ListPools(ctx) if err != nil { return } } for _, pool := range pools { sl, err := c.ListMembers(ctx, pool) if err != nil { return nil, err } for _, srv := range sl { if id != -1 && srv.ID == id { srv.Pool = pool return srv, nil } if servername != "" && srv.Name == servername { srv.Pool = pool return srv, nil } } } return nil, ErrServerNotFound } func (c *PoolClient) FindServerByName(ctx context.Context, poolname, servername string) (s *ServerRef, err error) { return c.FindServer(ctx, poolname, servername, -1) } func (c *PoolClient) FindServerByID(ctx context.Context, poolname string, id int) (s *ServerRef, err error) { return c.FindServer(ctx, poolname, "", id) } func (c *PoolClient) FindServerByURL(ctx context.Context, url string) (s *ServerRef, err error) { pool, _, id, err := ParseURL(url) if err != nil { return } return c.FindServerByID(ctx, pool, id) }