go/svc/(dc stuff) -> dc/
We want to start keeping codebases separated per 'team'/intent, to then
have simple OWNER files/trees to specify review rules.
This means dc/ stuff can all be OWNED by q3k, and review will only
involve a +1 for style/readability, instead of a +2 for approval.
Change-Id: I05afbc4e1018944b841ec0d88cd24cc95bec8bf1
diff --git a/dc/topo/state/BUILD.bazel b/dc/topo/state/BUILD.bazel
new file mode 100644
index 0000000..892e302
--- /dev/null
+++ b/dc/topo/state/BUILD.bazel
@@ -0,0 +1,14 @@
+load("@io_bazel_rules_go//go:def.bzl", "go_library")
+
+go_library(
+ name = "go_default_library",
+ srcs = ["state.go"],
+ importpath = "code.hackerspace.pl/hscloud/dc/topo/state",
+ visibility = ["//visibility:public"],
+ deps = [
+ "//dc/topo/proto:go_default_library",
+ "//go/pki:go_default_library",
+ "//proto/infra:go_default_library",
+ "@org_golang_google_grpc//:go_default_library",
+ ],
+)
diff --git a/dc/topo/state/state.go b/dc/topo/state/state.go
new file mode 100644
index 0000000..116a55a
--- /dev/null
+++ b/dc/topo/state/state.go
@@ -0,0 +1,76 @@
+package state
+
+import (
+ "context"
+ "fmt"
+ "sync"
+
+ "google.golang.org/grpc"
+
+ "code.hackerspace.pl/hscloud/go/pki"
+ ipb "code.hackerspace.pl/hscloud/proto/infra"
+
+ pb "code.hackerspace.pl/hscloud/dc/topo/proto"
+)
+
+type SwitchportState struct {
+ Proto *ipb.SwitchPort
+}
+
+type SwitchState struct {
+ Name string
+ Ports []*SwitchportState
+ Stub ipb.SwitchControlClient
+}
+
+func (s *SwitchState) Fetch(ctx context.Context) error {
+ req := ipb.GetPortsRequest{}
+ res, err := s.Stub.GetPorts(ctx, &req)
+ if err != nil {
+ return fmt.Errorf("GetPorts: %v", err)
+ }
+ s.Ports = make([]*SwitchportState, len(res.Ports))
+ for i, port := range res.Ports {
+ s.Ports[i] = &SwitchportState{port}
+ }
+ return nil
+}
+
+type StateManager struct {
+ Switches map[string]*SwitchState
+ Conns map[string]*grpc.ClientConn
+ Mu sync.RWMutex
+}
+
+func NewManager() *StateManager {
+ return &StateManager{
+ Switches: make(map[string]*SwitchState),
+ Conns: make(map[string]*grpc.ClientConn),
+ }
+}
+
+func (s *StateManager) FetchState(ctx context.Context, conf *pb.Config) error {
+ s.Mu.Lock()
+ defer s.Mu.Unlock()
+ for _, sw := range conf.Switch {
+ conn, ok := s.Conns[sw.ControlAddress]
+ if !ok {
+ var err error
+ conn, err = grpc.Dial(sw.ControlAddress, pki.WithClientHSPKI())
+ if err != nil {
+ return fmt.Errorf("when connecting to switch %s: %v", sw.Name, err)
+ }
+ s.Conns[sw.ControlAddress] = conn
+ }
+
+ s.Switches[sw.Name] = &SwitchState{
+ Name: sw.Name,
+ Stub: ipb.NewSwitchControlClient(conn),
+ }
+ err := s.Switches[sw.Name].Fetch(ctx)
+ if err != nil {
+ return fmt.Errorf("%q.Fetch: %v", sw.Name, err)
+ }
+ }
+ return nil
+}