Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.

Commit 1c52257

Browse files
committed
feat: Add Create RPC to dhclientd (#10)
1 parent abe74da commit 1c52257

File tree

9 files changed

+700
-5
lines changed

9 files changed

+700
-5
lines changed

cmd/constants.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package cmd
22

33
const (
4-
DHCPDDHostPortDefault = "localhost:1240" // DHCPDDHostPortDefault is the default Host:port that of `dhcpdd`.
4+
DHCPDDHostPortDefault = "localhost:1240" // DHCPDDHostPortDefault is the default Host:port of `dhcpdd`.
5+
DHClientDHostPortDefault = "localhost:1241" // DHClientDHostPortDefault is the default Host:port of `dhclient`.
56
)
67

78
const (

cmd/dhclientd/main.go

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package main
2+
3+
import (
4+
constants "github.com/pojntfx/godhcpd/cmd"
5+
godhcpd "github.com/pojntfx/godhcpd/pkg/proto/generated"
6+
"github.com/pojntfx/godhcpd/pkg/svc"
7+
"github.com/pojntfx/godhcpd/pkg/workers"
8+
"github.com/spf13/cobra"
9+
"github.com/spf13/viper"
10+
"gitlab.com/bloom42/libs/rz-go"
11+
"gitlab.com/bloom42/libs/rz-go/log"
12+
"google.golang.org/grpc"
13+
"google.golang.org/grpc/reflection"
14+
"net"
15+
"os"
16+
"os/signal"
17+
"path/filepath"
18+
"strings"
19+
"syscall"
20+
)
21+
22+
const (
23+
keyPrefix = "dhclientd."
24+
configFileDefault = ""
25+
configFileKey = keyPrefix + "configFile"
26+
listenHostPortKey = keyPrefix + "listenHostPort"
27+
)
28+
29+
var rootCmd = &cobra.Command{
30+
Use: "dhclientd",
31+
Short: "dhclientd is the ISC DHCP client management daemon",
32+
Long: `dhclientd is the ISC DHCP client management daemon.
33+
34+
Find more information at:
35+
https://pojntfx.github.io/godhcpd/`,
36+
PersistentPreRun: func(cmd *cobra.Command, args []string) {
37+
viper.SetEnvPrefix("dhclientd")
38+
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_", ".", "_"))
39+
},
40+
RunE: func(cmd *cobra.Command, args []string) error {
41+
if !(viper.GetString(configFileKey) == configFileDefault) {
42+
viper.SetConfigFile(viper.GetString(configFileKey))
43+
44+
if err := viper.ReadInConfig(); err != nil {
45+
return err
46+
}
47+
}
48+
binaryDir := filepath.Join(os.TempDir(), "dhclient")
49+
50+
listener, err := net.Listen("tcp", viper.GetString(listenHostPortKey))
51+
if err != nil {
52+
return err
53+
}
54+
55+
server := grpc.NewServer()
56+
reflection.Register(server)
57+
58+
DHClientService := svc.DHClientManager{
59+
BinaryDir: binaryDir,
60+
DHClientsManaged: make(map[string]*workers.DHClient),
61+
}
62+
63+
godhcpd.RegisterDHClientManagerServer(server, &DHClientService)
64+
65+
interrupt := make(chan os.Signal, 2)
66+
signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)
67+
go func() {
68+
<-interrupt
69+
70+
// Allow manually killing the process
71+
go func() {
72+
<-interrupt
73+
74+
os.Exit(1)
75+
}()
76+
77+
log.Info("Gracefully stopping server (this might take a few seconds)")
78+
79+
msg := "Could not stop dhcp server"
80+
81+
for _, DHClient := range DHClientService.DHClientsManaged {
82+
if err := DHClient.DisableAutoRestart(); err != nil { // Manually disable auto restart; disables crash recovery even if process is not running
83+
log.Fatal(msg, rz.Err(err))
84+
}
85+
86+
if DHClient.IsRunning() {
87+
if err := DHClient.Stop(); err != nil { // Stop is sync, so no need to `.Wait()`
88+
log.Fatal(msg, rz.Err(err))
89+
}
90+
}
91+
}
92+
93+
if err := DHClientService.Cleanup(); err != nil {
94+
log.Fatal(msg, rz.Err(err))
95+
}
96+
97+
server.GracefulStop()
98+
}()
99+
100+
if err := DHClientService.Extract(); err != nil {
101+
return err
102+
}
103+
104+
log.Info("Starting server")
105+
106+
if err := server.Serve(listener); err != nil {
107+
return err
108+
}
109+
110+
return nil
111+
},
112+
}
113+
114+
func init() {
115+
var (
116+
configFileFlag string
117+
hostPortFlag string
118+
)
119+
120+
rootCmd.PersistentFlags().StringVarP(&configFileFlag, configFileKey, "f", configFileDefault, "Configuration file to use.")
121+
rootCmd.PersistentFlags().StringVarP(&hostPortFlag, listenHostPortKey, "l", constants.DHClientDHostPortDefault, "TCP listen host:port.")
122+
123+
if err := viper.BindPFlags(rootCmd.PersistentFlags()); err != nil {
124+
log.Fatal(constants.CouldNotBindFlagsErrorMessage, rz.Err(err))
125+
}
126+
127+
viper.AutomaticEnv()
128+
}
129+
130+
func main() {
131+
if err := rootCmd.Execute(); err != nil {
132+
log.Fatal(constants.CouldNotStartRootCommandErrorMessage, rz.Err(err))
133+
}
134+
}

go.sum

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
2424
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
2525
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
2626
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
27+
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
2728
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
2829
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
2930
github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY=

pkg/proto/dhclient.proto

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
syntax = "proto3";
2+
3+
package godhcpd;
4+
5+
// DHClientManager manages DHCP clients.
6+
service DHClientManager {
7+
rpc Create(DHClient) returns (DHClientManagedId) {};
8+
rpc List(DHClientManagerListArgs) returns (DHClientManagerListReply) {};
9+
rpc Get(DHClientManagedId) returns (DHClientManaged) {};
10+
rpc Delete(DHClientManagedId) returns (DHClientManagedId) {};
11+
}
12+
13+
message DHClient { string Device = 1; }
14+
15+
message DHClientManaged {
16+
string Id = 1;
17+
string Device = 2;
18+
}
19+
20+
message DHClientManagerListArgs {}
21+
22+
message DHClientManagedId { string Id = 1; }
23+
24+
message DHClientManagerListReply {
25+
repeated DHClientManaged DHClientsManaged = 1;
26+
}

0 commit comments

Comments
 (0)