Skip to content

Commit

Permalink
Embedded etcd
Browse files Browse the repository at this point in the history
This monster patch embeds the etcd server. It took a good deal of
iterative work to tweak small details, and survived a rewrite from the
initial etcd v2 API implementation to the beta version of v3.

It has a notable race, and is missing some features, but it is ready for
git master and external developer consumption.
  • Loading branch information
purpleidea committed Jun 18, 2016
1 parent 715a4bf commit 5363839
Show file tree
Hide file tree
Showing 8 changed files with 2,275 additions and 296 deletions.
2 changes: 1 addition & 1 deletion DOCUMENTATION.md
Expand Up @@ -201,7 +201,7 @@ sudo mkdir -p /etc/systemd/system/mgmt.service.d/


cat > /etc/systemd/system/mgmt.service.d/env.conf <<EOF cat > /etc/systemd/system/mgmt.service.d/env.conf <<EOF
# Environment variables: # Environment variables:
MGMT_SEED_ENDPOINT=http://127.0.0.1:2379 MGMT_SEEDS=http://127.0.0.1:2379
MGMT_CONVERGED_TIMEOUT=-1 MGMT_CONVERGED_TIMEOUT=-1
MGMT_MAX_RUNTIME=0 MGMT_MAX_RUNTIME=0
Expand Down
1 change: 0 additions & 1 deletion README.md
Expand Up @@ -17,7 +17,6 @@ If you have a well phrased question that might benefit others, consider asking i
## Quick start: ## Quick start:
* Either get the golang dependencies on your own, or run `make deps` if you're comfortable with how we install them. * Either get the golang dependencies on your own, or run `make deps` if you're comfortable with how we install them.
* Run `make build` to get a freshly built `mgmt` binary. * Run `make build` to get a freshly built `mgmt` binary.
* Run `cd $(mktemp --tmpdir -d tmp.XXX) && etcd` to get etcd running. The `mgmt` software will do this automatically for you in the future.
* Run `time ./mgmt run --file examples/graph0.yaml --converged-timeout=1` to try out a very simple example! * Run `time ./mgmt run --file examples/graph0.yaml --converged-timeout=1` to try out a very simple example!
* To run continuously in the default mode of operation, omit the `--converged-timeout` option. * To run continuously in the default mode of operation, omit the `--converged-timeout` option.
* Have fun hacking on our future technology! * Have fun hacking on our future technology!
Expand Down
121 changes: 68 additions & 53 deletions config.go
Expand Up @@ -85,7 +85,7 @@ func ParseConfigFromFile(filename string) *GraphConfig {


// NewGraphFromConfig returns a new graph from existing input, such as from the // NewGraphFromConfig returns a new graph from existing input, such as from the
// existing graph, and a GraphConfig struct. // existing graph, and a GraphConfig struct.
func (g *Graph) NewGraphFromConfig(config *GraphConfig, etcdO *EtcdWObject, hostname string, noop bool) (*Graph, error) { func (g *Graph) NewGraphFromConfig(config *GraphConfig, embdEtcd *EmbdEtcd, hostname string, noop bool) (*Graph, error) {


var graph *Graph // new graph to return var graph *Graph // new graph to return
if g == nil { // FIXME: how can we check for an empty graph? if g == nil { // FIXME: how can we check for an empty graph?
Expand All @@ -101,8 +101,8 @@ func (g *Graph) NewGraphFromConfig(config *GraphConfig, etcdO *EtcdWObject, host
// TODO: if defined (somehow)... // TODO: if defined (somehow)...
graph.SetName(config.Graph) // set graph name graph.SetName(config.Graph) // set graph name


var keep []*Vertex // list of vertex which are the same in new graph var keep []*Vertex // list of vertex which are the same in new graph

var resources []Res // list of resources to export
// use reflection to avoid duplicating code... better options welcome! // use reflection to avoid duplicating code... better options welcome!
value := reflect.Indirect(reflect.ValueOf(config.Resources)) value := reflect.Indirect(reflect.ValueOf(config.Resources))
vtype := value.Type() vtype := value.Type()
Expand All @@ -118,91 +118,106 @@ func (g *Graph) NewGraphFromConfig(config *GraphConfig, etcdO *EtcdWObject, host
} }
for j := 0; j < slice.Len(); j++ { // loop through resources of same kind for j := 0; j < slice.Len(); j++ { // loop through resources of same kind
x := slice.Index(j).Interface() x := slice.Index(j).Interface()
obj, ok := x.(Res) // convert to Res type res, ok := x.(Res) // convert to Res type
if !ok { if !ok {
return nil, fmt.Errorf("Error: Config: Can't convert: %v of type: %T to Res.", x, x) return nil, fmt.Errorf("Error: Config: Can't convert: %v of type: %T to Res.", x, x)
} }
if noop { if noop {
obj.Meta().Noop = noop res.Meta().Noop = noop
} }
if _, exists := lookup[kind]; !exists { if _, exists := lookup[kind]; !exists {
lookup[kind] = make(map[string]*Vertex) lookup[kind] = make(map[string]*Vertex)
} }
// XXX: should we export based on a @@ prefix, or a metaparam // XXX: should we export based on a @@ prefix, or a metaparam
// like exported => true || exported => (host pattern)||(other pattern?) // like exported => true || exported => (host pattern)||(other pattern?)
if !strings.HasPrefix(obj.GetName(), "@@") { // exported resource if !strings.HasPrefix(res.GetName(), "@@") { // not exported resource
// XXX: we don't have a way of knowing if any of the // XXX: we don't have a way of knowing if any of the
// metaparams are undefined, and as a result to set the // metaparams are undefined, and as a result to set the
// defaults that we want! I hate the go yaml parser!!! // defaults that we want! I hate the go yaml parser!!!
v := graph.GetVertexMatch(obj) v := graph.GetVertexMatch(res)
if v == nil { // no match found if v == nil { // no match found
obj.Init() res.Init()
v = NewVertex(obj) v = NewVertex(res)
graph.AddVertex(v) // call standalone in case not part of an edge graph.AddVertex(v) // call standalone in case not part of an edge
} }
lookup[kind][obj.GetName()] = v // used for constructing edges lookup[kind][res.GetName()] = v // used for constructing edges
keep = append(keep, v) // append keep = append(keep, v) // append


} else if !noop { // do not export any resources if noop } else if !noop { // do not export any resources if noop
// XXX: do this in a different function... // store for addition to etcd storage...
// add to etcd storage... res.SetName(res.GetName()[2:]) //slice off @@
obj.SetName(obj.GetName()[2:]) //slice off @@ res.setKind(kind) // cheap init

resources = append(resources, res)
data, err := ResToB64(obj)
if err != nil {
return nil, fmt.Errorf("Config: Could not encode %v resource: %v, error: %v", kind, obj.GetName(), err)
}

if !etcdO.EtcdPut(hostname, obj.GetName(), kind, data) {
return nil, fmt.Errorf("Config: Could not export %v resource: %v", kind, obj.GetName())
}
} }
} }
} }
// store in etcd
if err := EtcdSetResources(embdEtcd, hostname, resources); err != nil {
return nil, fmt.Errorf("Config: Could not export resources: %v", err)
}


// lookup from etcd graph // lookup from etcd
var hostnameFilter []string // empty to get from everyone
kindFilter := []string{}
for _, t := range config.Collector {
// XXX: should we just drop these everywhere and have the kind strings be all lowercase?
kind := FirstToUpper(t.Kind)
kindFilter = append(kindFilter, kind)
}
// do all the graph look ups in one single step, so that if the etcd // do all the graph look ups in one single step, so that if the etcd
// database changes, we don't have a partial state of affairs... // database changes, we don't have a partial state of affairs...
nodes, ok := etcdO.EtcdGet() if len(kindFilter) > 0 { // if kindFilter is empty, don't need to do lookups!
if ok { var err error
resources, err = EtcdGetResources(embdEtcd, hostnameFilter, kindFilter)
if err != nil {
return nil, fmt.Errorf("Config: Could not collect resources: %v", err)
}
}
for _, res := range resources {
matched := false
// see if we find a collect pattern that matches
for _, t := range config.Collector { for _, t := range config.Collector {
// XXX: should we just drop these everywhere and have the kind strings be all lowercase? // XXX: should we just drop these everywhere and have the kind strings be all lowercase?
kind := FirstToUpper(t.Kind) kind := FirstToUpper(t.Kind)

// use t.Kind and optionally t.Pattern to collect from etcd storage // use t.Kind and optionally t.Pattern to collect from etcd storage
log.Printf("Collect: %v; Pattern: %v", kind, t.Pattern) log.Printf("Collect: %v; Pattern: %v", kind, t.Pattern)
for _, str := range etcdO.EtcdGetProcess(nodes, kind) {
obj, err := B64ToRes(str)
if err != nil {
log.Printf("B64ToRes failed to decode: %v", err)
log.Printf("Collect: %v: not collected!", kind)
continue
}


// collect resources but add the noop metaparam // XXX: expand to more complex pattern matching here...
if noop { if res.Kind() != kind {
obj.Meta().Noop = noop continue
} }


if t.Pattern != "" { // XXX: simplistic for now if matched {
obj.CollectPattern(t.Pattern) // obj.Dirname = t.Pattern // we've already matched this resource, should we match again?
} log.Printf("Config: Warning: Matching %v[%v] again!", kind, res.GetName())
}
matched = true


log.Printf("Collect: %v[%v]: collected!", kind, obj.GetName()) // collect resources but add the noop metaparam
if noop {
res.Meta().Noop = noop
}


// XXX: similar to other resource add code: if t.Pattern != "" { // XXX: simplistic for now
if _, exists := lookup[kind]; !exists { res.CollectPattern(t.Pattern) // res.Dirname = t.Pattern
lookup[kind] = make(map[string]*Vertex) }
}
v := graph.GetVertexMatch(obj) log.Printf("Collect: %v[%v]: collected!", kind, res.GetName())
if v == nil { // no match found
obj.Init() // initialize go channels or things won't work!!! // XXX: similar to other resource add code:
v = NewVertex(obj) if _, exists := lookup[kind]; !exists {
graph.AddVertex(v) // call standalone in case not part of an edge lookup[kind] = make(map[string]*Vertex)
}
lookup[kind][obj.GetName()] = v // used for constructing edges
keep = append(keep, v) // append
} }
v := graph.GetVertexMatch(res)
if v == nil { // no match found
res.Init() // initialize go channels or things won't work!!!
v = NewVertex(res)
graph.AddVertex(v) // call standalone in case not part of an edge
}
lookup[kind][res.GetName()] = v // used for constructing edges
keep = append(keep, v) // append

//break // let's see if another resource even matches
} }
} }


Expand Down

0 comments on commit 5363839

Please sign in to comment.