blob: 8f26e0bf906d6d080db6c0b9abd5cfa378046f4a [file] [log] [blame]
Sergiusz Bazanskiff5af692018-08-29 19:20:46 +01001package main
2
3import (
4 "context"
5 "flag"
6 "net"
7 "net/http"
8
9 "code.hackerspace.pl/q3k/hspki"
10 "github.com/golang/glog"
11 "github.com/q3k/statusz"
12 "github.com/ziutek/telnet"
13 "golang.org/x/net/trace"
14 "google.golang.org/grpc"
15 "google.golang.org/grpc/codes"
16 "google.golang.org/grpc/reflection"
17 "google.golang.org/grpc/status"
18
19 pb "code.hackerspace.pl/q3k/m6220-proxy/proto"
20)
21
22var (
23 flagListenAddress string
24 flagDebugAddress string
25 flagSwitchAddress string
26 flagSwitchUsername string
27 flagSwitchPassword string
28)
29
30func init() {
31 flag.Set("logtostderr", "true")
32}
33
34type service struct {
35 connectionSemaphore chan int
36}
37
38func (s *service) connect() (*cliClient, error) {
39 s.connectionSemaphore <- 1
40 conn, err := telnet.Dial("tcp", flagSwitchAddress)
41 if err != nil {
42 <-s.connectionSemaphore
43 return nil, err
44 }
45
46 cli := newCliClient(conn, flagSwitchUsername, flagSwitchPassword)
47 return cli, nil
48}
49
50func (s *service) disconnect() {
51 <-s.connectionSemaphore
52}
53
54func (s *service) RunCommand(ctx context.Context, req *pb.RunCommandRequest) (*pb.RunCommandResponse, error) {
55 if req.Command == "" {
56 return nil, status.Error(codes.InvalidArgument, "command cannot be null")
57 }
58
59 cli, err := s.connect()
60 if err != nil {
61 return nil, status.Error(codes.Unavailable, "could not connect to backend")
62 }
63 defer s.disconnect()
64
65 lines, effective, err := cli.runCommand(ctx, req.Command)
66 if err != nil {
67 return nil, err
68 }
69 res := &pb.RunCommandResponse{
70 EffectiveCommand: effective,
71 Lines: lines,
72 }
73 return res, nil
74}
75
76func main() {
77 flag.StringVar(&flagListenAddress, "listen_address", "127.0.0.1:42000", "Address to listen on for gRPC")
78 flag.StringVar(&flagDebugAddress, "debug_address", "127.0.0.1:42001", "Address to listen on for Debug HTTP")
79 flag.StringVar(&flagSwitchAddress, "switch_address", "127.0.0.1:23", "Telnet address of M6220")
80 flag.StringVar(&flagSwitchUsername, "switch_username", "admin", "Switch login username")
81 flag.StringVar(&flagSwitchPassword, "switch_password", "admin", "Switch login password")
82 flag.Parse()
83
84 s := &service{
85 connectionSemaphore: make(chan int, 1),
86 }
87
88 grpc.EnableTracing = true
89 grpcLis, err := net.Listen("tcp", flagListenAddress)
90 if err != nil {
91 glog.Exitf("Could not listen on %v: %v", flagListenAddress, err)
92 }
93 grpcSrv := grpc.NewServer(hspki.WithServerHSPKI()...)
94 pb.RegisterM6220ProxyServer(grpcSrv, s)
95 reflection.Register(grpcSrv)
96
97 glog.Infof("Starting gRPC on %v", flagListenAddress)
98 go func() {
99 if err := grpcSrv.Serve(grpcLis); err != nil {
100 glog.Exitf("Could not start gRPC: %v", err)
101 }
102 }()
103
104 if flagDebugAddress != "" {
105 glog.Infof("Starting debug on %v", flagDebugAddress)
106 httpMux := http.NewServeMux()
107 httpMux.HandleFunc("/debug/status", statusz.StatusHandler)
108 httpMux.HandleFunc("/debug/requests", trace.Traces)
109 httpMux.HandleFunc("/", statusz.StatusHandler)
110
111 httpLis, err := net.Listen("tcp", flagDebugAddress)
112 if err != nil {
113 glog.Exitf("Could not listen on %v: %v", flagDebugAddress, err)
114 }
115 httpSrv := &http.Server{
116 Addr: flagDebugAddress,
117 Handler: httpMux,
118 }
119
120 go func() {
121 if err := httpSrv.Serve(httpLis); err != nil {
122 glog.Exitf("Could not start HTTP server: %v", err)
123 }
124 }()
125
126 }
127
128 glog.Infof("Running!")
129
130 select {}
131}