diff --git a/node.go b/node.go index 70ac72c..7863d90 100644 --- a/node.go +++ b/node.go @@ -9,7 +9,6 @@ import ( ) var ( - ErrServerNotFound = errors.New("server not found") ErrNodesOffline = errors.New("one or more nodes are offline") ErrNodesNotSearched = errors.New("one or more nodes could not be searched") ) @@ -29,8 +28,6 @@ type Node struct { type NodeList []*Node -type ServerList []*Server - type NodeClient struct { client *Client } @@ -106,5 +103,5 @@ func (c *NodeClient) FindServerByURL(ctx context.Context, url string) (s *Server if err != nil { return } - return c.FindServer(ctx, "", id) + return c.FindServerByID(ctx, id) } diff --git a/pool.go b/pool.go index e675d1d..f42d636 100644 --- a/pool.go +++ b/pool.go @@ -72,3 +72,50 @@ func (c *PoolClient) Delete(ctx context.Context, name string) (err error) { _, err = c.client.Do(req, nil) return } + +type pool struct { + members ServerList `json:"members"` +} + +func (c *PoolClient) List(ctx context.Context, name string) (sl ServerList, err error) { + 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 + return +} + +func (c *PoolClient) FindServer(ctx context.Context, poolname, servername, id string) (s *Server, err error) { + sl, err := c.List(ctx, poolname) + if err != nil { + return + } + for _, srv := range sl { + if id != "" && srv.ID == id { + return srv, nil + } + if servername != "" && srv.Name == servername { + return srv, nil + } + } + return nil, ErrServerNotFound +} + +func (c *PoolClient) FindServerByName(ctx context.Context, poolname, servername string) (s *Server, err error) { + return c.FindServer(ctx, poolname, servername, "") +} + +func (c *PoolClient) FindServerByID(ctx context.Context, poolname, id string) (s *Server, err error) { + return c.FindServer(ctx, poolname, "", id) +} + +func (c *PoolClient) FindServerByURL(ctx context.Context, url string) (s *Server, err error) { + pool, id, err := ParseURL(url) + if err != nil { + return + } + return c.FindServerByID(ctx, pool, id) +} diff --git a/scheme.go b/scheme.go index 57d19fc..2f5b2a9 100644 --- a/scheme.go +++ b/scheme.go @@ -13,7 +13,7 @@ const PVEScheme = "pve" var ErrInvalidPVEURL = errors.New("invalid pve url scheme") -func ParseURL(s string) (node, id string, err error) { +func ParseURL(s string) (pool, id string, err error) { u, err := url.Parse(s) if err != nil { return @@ -25,6 +25,6 @@ func ParseURL(s string) (node, id string, err error) { return u.Host, strings.TrimPrefix(u.Path, "/"), nil } -func NewURL(node, id string) string { - return fmt.Sprintf("%s://%s/%s", PVEScheme, node, id) +func NewURL(pool, id string) string { + return fmt.Sprintf("%s://%s/%s", PVEScheme, pool, id) } diff --git a/server.go b/server.go index 301beaf..77e33d4 100644 --- a/server.go +++ b/server.go @@ -10,6 +10,10 @@ import ( "strings" ) +var ErrServerNotFound = errors.New("server not found") + +type ServerList []*Server + type Server struct { ID string `json:"vmid"` Name string `json:"name"` @@ -180,11 +184,26 @@ func (c *ServerClient) getServer(ctx context.Context, node, id string) (s *Serve } func (c *ServerClient) GetByURL(ctx context.Context, url string) (s *Server, err error) { - node, id, err := ParseURL(url) + pool, id, err := ParseURL(url) if err != nil { return } - s, cfg, err := c.getServer(ctx, node, id) + var srv *Server + if pool != "" { + srv, err = c.client.Pool.FindServerByID(ctx, pool, id) + if err == ErrServerNotFound { + return + } + } + srv, err = c.client.Node.FindServerByID(ctx, id) + if err != nil { + return + } + if srv == nil { + err = ErrServerNotFound + return + } + s, cfg, err := c.getServer(ctx, srv.Node, srv.ID) if err != nil { return } @@ -200,7 +219,8 @@ func (c *ServerClient) GetByURL(ctx context.Context, url string) (s *Server, err type ServerTemplateOpts struct { Name string - TemplateURL string + TemplateID string + TemplateNode string Pool string TargetStorage string TargetNode string @@ -210,8 +230,11 @@ func (o ServerTemplateOpts) Validate() error { if o.Name == "" { return errors.New("missing name") } - if o.TemplateURL == "" { - return errors.New("missing template url") + if o.TemplateID == "" { + return errors.New("missing template id") + } + if o.TemplateNode == "" { + return errors.New("missing template node") } return nil } @@ -233,23 +256,17 @@ func (c *ServerClient) CreateFromTemplate(ctx context.Context, opts ServerTempla if err != nil { return } - tempnode, id, err := ParseURL(opts.TemplateURL) - if err != nil { - return - } nextid, err := c.NextID(ctx) if err != nil { return } body := opts.body() body["newid"] = nextid - if opts.TargetNode != "" && tempnode != opts.TargetNode { + if opts.TargetNode != "" && opts.TemplateNode != opts.TargetNode { body["target"] = opts.TargetNode - url = NewURL(opts.TargetNode, nextid) - } else { - url = NewURL(tempnode, nextid) } - req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("/nodes/%s/qemu/%s/clone", tempnode, id), body.Reader()) + url = NewURL(opts.Pool, nextid) + req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("/nodes/%s/qemu/%s/clone", opts.TemplateNode, opts.TemplateID), body.Reader()) if err != nil { return }