Continue reorganization, add asinkd stop cmd, make asinkd socket configurable

This commit is contained in:
Aaron Lindsay 2013-09-02 23:35:48 -04:00
parent 2599717d09
commit 4eb75e1db1
15 changed files with 55 additions and 11 deletions

View File

@ -13,6 +13,7 @@ var exitWaiterChan chan int
func init() { func init() {
exitWaiterCount = 0 exitWaiterCount = 0
exitWaiterChan = make(chan int) exitWaiterChan = make(chan int)
exitCalled = make(chan int)
go setupCleanExitOnSignals() go setupCleanExitOnSignals()
} }

View File

@ -17,6 +17,11 @@ var commands []Command = []Command{
fn: StartServer, fn: StartServer,
explanation: "Start the server daemon", explanation: "Start the server daemon",
}, },
Command{
cmd: "stop",
fn: StopServer,
explanation: "Stop the server daemon",
},
Command{ Command{
cmd: "useradd", cmd: "useradd",
fn: UserAdd, fn: UserAdd,

View File

@ -7,8 +7,7 @@ import (
"syscall" "syscall"
) )
func RPCCall(method string, args interface{}, reply interface{}) error { func RPCCall(socket, method string, args interface{}, reply interface{}) error {
socket := "/tmp/asink.sock"
client, err := rpc.DialHTTP("unix", socket) client, err := rpc.DialHTTP("unix", socket)
if err != nil { if err != nil {
if err2, ok := err.(*net.OpError); ok { if err2, ok := err.(*net.OpError); ok {

View File

@ -65,15 +65,26 @@ func (u *UserModifier) RemoveUser(user *User, result *int) error {
return err return err
} }
func StartRPC(tornDown chan int, adb *AsinkDB) { type ServerStopper int
func (s *ServerStopper) StopServer(code *int, result *int) error {
Exit(*code)
*result = 0
return nil
}
func StartRPC(sock string, tornDown chan int, adb *AsinkDB) {
defer func() { tornDown <- 0 }() //the main thread waits for this to ensure the socket is closed defer func() { tornDown <- 0 }() //the main thread waits for this to ensure the socket is closed
usermod := new(UserModifier) usermod := new(UserModifier)
usermod.adb = adb usermod.adb = adb
rpc.Register(usermod) rpc.Register(usermod)
serverstop := new(ServerStopper)
rpc.Register(serverstop)
rpc.HandleHTTP() rpc.HandleHTTP()
l, err := net.Listen("unix", "/tmp/asink.sock") l, err := net.Listen("unix", sock)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View File

@ -17,6 +17,7 @@ import (
//global variables //global variables
var eventsRegexp *regexp.Regexp var eventsRegexp *regexp.Regexp
var port int = 8080 var port int = 8080
var rpcSock string
var adb *AsinkDB var adb *AsinkDB
func init() { func init() {
@ -30,17 +31,21 @@ func init() {
} }
} }
const sock_usage = "Socket to use to connect to the Asink server."
const sock_default = "/var/run/asink/asinkd.sock"
func StartServer(args []string) { func StartServer(args []string) {
const port_usage = "Port on which to serve HTTP API" const port_usage = "Port on which to serve HTTP API"
flags := flag.NewFlagSet("start", flag.ExitOnError) flags := flag.NewFlagSet("start", flag.ExitOnError)
flags.IntVar(&port, "port", 8080, port_usage) flags.IntVar(&port, "port", 8080, port_usage)
flags.IntVar(&port, "p", 8080, port_usage+" (shorthand)") flags.IntVar(&port, "p", 8080, port_usage+" (shorthand)")
flags.StringVar(&rpcSock, "sock", sock_default, sock_usage)
flags.StringVar(&rpcSock, "s", sock_default, sock_usage+" (shorthand)")
flags.Parse(args) flags.Parse(args)
rpcTornDown := make(chan int) rpcTornDown := make(chan int)
go StartRPC(rpcTornDown, adb) go StartRPC(rpcSock, rpcTornDown, adb)
http.HandleFunc("/", rootHandler) http.HandleFunc("/", rootHandler)
http.HandleFunc("/events", eventHandler) http.HandleFunc("/events", eventHandler)
@ -59,6 +64,20 @@ func StartServer(args []string) {
<-rpcTornDown <-rpcTornDown
} }
func StopServer(args []string) {
flags := flag.NewFlagSet("stop", flag.ExitOnError)
flags.StringVar(&rpcSock, "sock", sock_default, sock_usage)
flags.StringVar(&rpcSock, "s", sock_default, sock_usage+" (shorthand)")
flags.Parse(args)
i := 99
returnCode := 0
err := RPCCall(rpcSock, "ServerStopper.StopServer", &returnCode, &i)
if err != nil {
panic(err)
}
}
func rootHandler(w http.ResponseWriter, r *http.Request) { func rootHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "You're probably looking for /events/") fmt.Fprintf(w, "You're probably looking for /events/")
} }

View File

@ -27,6 +27,9 @@ func (b *boolIsSetFlag) Set(value string) error {
return err return err
} }
const rpcSocketDefault = "/var/run/asink/asinkd.sock"
const rpcSocketDescription = "Socket to use to connect to the Asink server."
func (b *boolIsSetFlag) String() string { return fmt.Sprintf("%v", *b) } func (b *boolIsSetFlag) String() string { return fmt.Sprintf("%v", *b) }
func (b *boolIsSetFlag) IsBoolFlag() bool { return true } func (b *boolIsSetFlag) IsBoolFlag() bool { return true }
@ -34,6 +37,7 @@ func (b *boolIsSetFlag) IsBoolFlag() bool { return true }
func UserAdd(args []string) { func UserAdd(args []string) {
flags := flag.NewFlagSet("useradd", flag.ExitOnError) flags := flag.NewFlagSet("useradd", flag.ExitOnError)
admin := flags.Bool("admin", false, "User should be an administrator") admin := flags.Bool("admin", false, "User should be an administrator")
rpcSocket := flags.String("sock", rpcSocketDefault, rpcSocketDescription)
flags.Parse(args) flags.Parse(args)
if flags.NArg() != 1 { if flags.NArg() != 1 {
@ -66,7 +70,7 @@ func UserAdd(args []string) {
user.PWHash = HashPassword(passwordOne) user.PWHash = HashPassword(passwordOne)
i := 99 i := 99
err = RPCCall("UserModifier.AddUser", user, &i) err = RPCCall(*rpcSocket, "UserModifier.AddUser", user, &i)
if err != nil { if err != nil {
if _, ok := err.(rpc.ServerError); ok && err.Error() == DuplicateUsernameErr.Error() { if _, ok := err.(rpc.ServerError); ok && err.Error() == DuplicateUsernameErr.Error() {
fmt.Println("Error: " + err.Error()) fmt.Println("Error: " + err.Error())
@ -77,7 +81,11 @@ func UserAdd(args []string) {
} }
func UserDel(args []string) { func UserDel(args []string) {
if len(args) != 1 { flags := flag.NewFlagSet("userdel", flag.ExitOnError)
rpcSocket := flags.String("sock", rpcSocketDefault, rpcSocketDescription)
flags.Parse(args)
if flags.NArg() != 1 {
fmt.Println("Error: please supply a username (and only one)") fmt.Println("Error: please supply a username (and only one)")
os.Exit(1) os.Exit(1)
} }
@ -86,7 +94,7 @@ func UserDel(args []string) {
user.Username = args[0] user.Username = args[0]
i := 99 i := 99
err := RPCCall("UserModifier.RemoveUser", user, &i) err := RPCCall(*rpcSocket, "UserModifier.RemoveUser", user, &i)
if err != nil { if err != nil {
if _, ok := err.(rpc.ServerError); ok && err.Error() == NoUserErr.Error() { if _, ok := err.(rpc.ServerError); ok && err.Error() == NoUserErr.Error() {
fmt.Println("Error: " + err.Error()) fmt.Println("Error: " + err.Error())
@ -109,6 +117,7 @@ func UserMod(args []string) {
flags.BoolVar(&rpcargs.UpdatePassword, "p", false, "Change the user's password (short version)") flags.BoolVar(&rpcargs.UpdatePassword, "p", false, "Change the user's password (short version)")
flags.BoolVar(&rpcargs.UpdateLogin, "login", false, "Change the user's username") flags.BoolVar(&rpcargs.UpdateLogin, "login", false, "Change the user's username")
flags.BoolVar(&rpcargs.UpdateLogin, "l", false, "Change the user's username (short version)") flags.BoolVar(&rpcargs.UpdateLogin, "l", false, "Change the user's username (short version)")
rpcSocket := flags.String("sock", rpcSocketDefault, rpcSocketDescription)
flags.Parse(args) flags.Parse(args)
if flags.NArg() != 1 { if flags.NArg() != 1 {
@ -153,7 +162,7 @@ func UserMod(args []string) {
} }
i := 99 i := 99
err := RPCCall("UserModifier.ModifyUser", rpcargs, &i) err := RPCCall(*rpcSocket, "UserModifier.ModifyUser", rpcargs, &i)
if err != nil { if err != nil {
if _, ok := err.(rpc.ServerError); ok && err.Error() == NoUserErr.Error() { if _, ok := err.(rpc.ServerError); ok && err.Error() == NoUserErr.Error() {
fmt.Println("Error: " + err.Error()) fmt.Println("Error: " + err.Error())