resources: Add VarDir support
This gives resources a private directory where they can store state.
This commit is contained in:
@@ -22,6 +22,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ import (
|
|||||||
"github.com/purpleidea/mgmt/pgraph"
|
"github.com/purpleidea/mgmt/pgraph"
|
||||||
"github.com/purpleidea/mgmt/recwatch"
|
"github.com/purpleidea/mgmt/recwatch"
|
||||||
"github.com/purpleidea/mgmt/remote"
|
"github.com/purpleidea/mgmt/remote"
|
||||||
|
"github.com/purpleidea/mgmt/resources"
|
||||||
"github.com/purpleidea/mgmt/util"
|
"github.com/purpleidea/mgmt/util"
|
||||||
|
|
||||||
etcdtypes "github.com/coreos/etcd/pkg/types"
|
etcdtypes "github.com/coreos/etcd/pkg/types"
|
||||||
@@ -205,6 +207,10 @@ func (obj *Main) Run() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Printf("Main: Working prefix is: %s", prefix)
|
log.Printf("Main: Working prefix is: %s", prefix)
|
||||||
|
pgraphPrefix := fmt.Sprintf("%s/", path.Join(prefix, "pgraph")) // pgraph namespace
|
||||||
|
if err := os.MkdirAll(pgraphPrefix, 0770); err != nil {
|
||||||
|
return errwrap.Wrapf(err, "Can't create pgraph prefix")
|
||||||
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
var G, oldGraph *pgraph.Graph
|
var G, oldGraph *pgraph.Graph
|
||||||
@@ -348,6 +354,12 @@ func (obj *Main) Run() error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pass in the information we need
|
||||||
|
newGraph.AssociateData(&resources.Data{
|
||||||
|
Converger: converger,
|
||||||
|
Prefix: pgraphPrefix,
|
||||||
|
})
|
||||||
|
|
||||||
// apply the global noop parameter if requested
|
// apply the global noop parameter if requested
|
||||||
if obj.Noop {
|
if obj.Noop {
|
||||||
for _, m := range newGraph.GraphMetas() {
|
for _, m := range newGraph.GraphMetas() {
|
||||||
@@ -383,7 +395,6 @@ func (obj *Main) Run() error {
|
|||||||
log.Printf("Graphviz: Successfully generated graph!")
|
log.Printf("Graphviz: Successfully generated graph!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
G.AssociateData(converger)
|
|
||||||
// G.Start(...) needs to be synchronous or wait,
|
// G.Start(...) needs to be synchronous or wait,
|
||||||
// because if half of the nodes are started and
|
// because if half of the nodes are started and
|
||||||
// some are not ready yet and the EtcdWatch
|
// some are not ready yet and the EtcdWatch
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/purpleidea/mgmt/converger"
|
|
||||||
"github.com/purpleidea/mgmt/event"
|
"github.com/purpleidea/mgmt/event"
|
||||||
"github.com/purpleidea/mgmt/global"
|
"github.com/purpleidea/mgmt/global"
|
||||||
"github.com/purpleidea/mgmt/resources"
|
"github.com/purpleidea/mgmt/resources"
|
||||||
@@ -1040,10 +1039,10 @@ func (g *Graph) GraphMetas() []*resources.MetaParams {
|
|||||||
return metas
|
return metas
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssociateData associates some data with the object in the graph in question
|
// AssociateData associates some data with the object in the graph in question.
|
||||||
func (g *Graph) AssociateData(converger converger.Converger) {
|
func (g *Graph) AssociateData(data *resources.Data) {
|
||||||
for v := range g.GetVerticesChan() {
|
for k := range g.Adjacency {
|
||||||
v.Res.AssociateData(converger)
|
k.Res.AssociateData(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,11 +24,15 @@ import (
|
|||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
// TODO: should each resource be a sub-package?
|
// TODO: should each resource be a sub-package?
|
||||||
"github.com/purpleidea/mgmt/converger"
|
"github.com/purpleidea/mgmt/converger"
|
||||||
"github.com/purpleidea/mgmt/event"
|
"github.com/purpleidea/mgmt/event"
|
||||||
"github.com/purpleidea/mgmt/global"
|
"github.com/purpleidea/mgmt/global"
|
||||||
|
|
||||||
|
errwrap "github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate stringer -type=ResState -output=resstate_stringer.go
|
//go:generate stringer -type=ResState -output=resstate_stringer.go
|
||||||
@@ -45,6 +49,15 @@ const (
|
|||||||
ResStatePoking
|
ResStatePoking
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Data is the set of input values passed into the pgraph for the resources.
|
||||||
|
type Data struct {
|
||||||
|
//Hostname string // uuid for the host
|
||||||
|
//Noop bool
|
||||||
|
Converger converger.Converger
|
||||||
|
Prefix string // the prefix to be used for the pgraph namespace
|
||||||
|
// NOTE: we can add more fields here if needed for the resources.
|
||||||
|
}
|
||||||
|
|
||||||
// ResUID is a unique identifier for a resource, namely it's name, and the kind ("type").
|
// ResUID is a unique identifier for a resource, namely it's name, and the kind ("type").
|
||||||
type ResUID interface {
|
type ResUID interface {
|
||||||
GetName() string
|
GetName() string
|
||||||
@@ -112,7 +125,7 @@ type Base interface {
|
|||||||
Kind() string
|
Kind() string
|
||||||
Meta() *MetaParams
|
Meta() *MetaParams
|
||||||
Events() chan event.Event
|
Events() chan event.Event
|
||||||
AssociateData(converger.Converger)
|
AssociateData(*Data)
|
||||||
IsWatching() bool
|
IsWatching() bool
|
||||||
SetWatching(bool)
|
SetWatching(bool)
|
||||||
GetState() ResState
|
GetState() ResState
|
||||||
@@ -126,6 +139,7 @@ type Base interface {
|
|||||||
SetGrouped(bool) // set grouped bool
|
SetGrouped(bool) // set grouped bool
|
||||||
GetGroup() []Res // return everyone grouped inside me
|
GetGroup() []Res // return everyone grouped inside me
|
||||||
SetGroup([]Res)
|
SetGroup([]Res)
|
||||||
|
VarDir(string) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Res is the minimum interface you need to implement to define a new resource.
|
// Res is the minimum interface you need to implement to define a new resource.
|
||||||
@@ -236,8 +250,9 @@ func (obj *BaseRes) Events() chan event.Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AssociateData associates some data with the object in question.
|
// AssociateData associates some data with the object in question.
|
||||||
func (obj *BaseRes) AssociateData(converger converger.Converger) {
|
func (obj *BaseRes) AssociateData(data *Data) {
|
||||||
obj.converger = converger
|
obj.converger = data.Converger
|
||||||
|
obj.prefix = data.Prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsWatching tells us if the Watch() function is running.
|
// IsWatching tells us if the Watch() function is running.
|
||||||
@@ -415,6 +430,30 @@ func (obj *BaseRes) CollectPattern(pattern string) {
|
|||||||
// XXX: default method is empty
|
// XXX: default method is empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VarDir returns the path to a working directory for the resource. It will try
|
||||||
|
// and create the directory first, and return an error if this failed.
|
||||||
|
func (obj *BaseRes) VarDir(extra string) (string, error) {
|
||||||
|
// Using extra adds additional dirs onto our namespace. An empty extra
|
||||||
|
// adds no additional directories.
|
||||||
|
if obj.prefix == "" {
|
||||||
|
return "", fmt.Errorf("VarDir prefix is empty!")
|
||||||
|
}
|
||||||
|
if obj.Kind() == "" {
|
||||||
|
return "", fmt.Errorf("VarDir kind is empty!")
|
||||||
|
}
|
||||||
|
if obj.GetName() == "" {
|
||||||
|
return "", fmt.Errorf("VarDir name is empty!")
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: is obj.GetName() sufficiently unique to use as a UID here?
|
||||||
|
uid := obj.GetName()
|
||||||
|
p := fmt.Sprintf("%s/", path.Join(obj.prefix, obj.Kind(), uid, extra))
|
||||||
|
if err := os.MkdirAll(p, 0770); err != nil {
|
||||||
|
return "", errwrap.Wrapf(err, "Can't create prefix for %s[%s]", obj.Kind(), obj.GetName())
|
||||||
|
}
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ResToB64 encodes a resource to a base64 encoded string (after serialization)
|
// ResToB64 encodes a resource to a base64 encoded string (after serialization)
|
||||||
func ResToB64(res Res) (string, error) {
|
func ResToB64(res Res) (string, error) {
|
||||||
b := bytes.Buffer{}
|
b := bytes.Buffer{}
|
||||||
|
|||||||
Reference in New Issue
Block a user