Skip to content

Commit

Permalink
Merge pull request #81 from shunfei/develop
Browse files Browse the repository at this point in the history
v0.3.2
  • Loading branch information
Doflatango authored Jun 10, 2018
2 parents 054ce02 + 8363e74 commit 9bb382d
Show file tree
Hide file tree
Showing 22 changed files with 339 additions and 65 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ dist
bin/*/*server
.DS_Store
web/ui/node_modules
web/ui/package-lock.json
web/ui/semantic.json
web/ui/semantic
web/ui/dist
.vscode
*npm-debug.log
Expand Down
5 changes: 4 additions & 1 deletion account.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ type Role int
const (
Administrator Role = 1
Developer Role = 2
Reporter Role = 3
)

func (r Role) Defined() bool {
switch r {
case Administrator, Developer:
case Administrator, Developer, Reporter:
return true
}
return false
Expand All @@ -45,6 +46,8 @@ func (r Role) String() string {
return "Administrator"
case Developer:
return "Developer"
case Reporter:
return "Reporter"
}
return "Undefined"
}
Expand Down
4 changes: 2 additions & 2 deletions bin/csctl/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ var rootCmd = &cobra.Command{
}

func init() {
rootCmd.PersistentFlags().StringVarP(&confFile, "conf", "c", "", "base.json file path.")
rootCmd.AddCommand(subcmd.BackupCmd, subcmd.RestoreCmd, subcmd.UpgradeCmd)
rootCmd.PersistentFlags().StringVarP(&confFile, "conf", "c", "conf/files/base.json", "base.json file path.")
rootCmd.AddCommand(subcmd.BackupCmd, subcmd.RestoreCmd, subcmd.UpgradeCmd, subcmd.NodeCmd)
}

func main() {
Expand Down
5 changes: 5 additions & 0 deletions bin/csctl/cmd/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func init() {

type ExitAction struct {
Defer func()
After func()
}

func NewExitAction() *ExitAction {
Expand All @@ -97,6 +98,10 @@ func (ea *ExitAction) Exit(format string, v ...interface{}) {
}

fmt.Printf(format+"\n", v...)

if ea.After != nil {
ea.After()
}
os.Exit(1)
}

Expand Down
65 changes: 65 additions & 0 deletions bin/csctl/cmd/node.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package cmd

import (
"fmt"
"strings"

"github.com/spf13/cobra"

"github.com/shunfei/cronsun"
)

var (
nodeCmd string
nodeInclude string
nodeExclude string

spliter = ","
)

func init() {
NodeCmd.Flags().StringVar(&nodeCmd, "cmd", "", "the command send to node")
NodeCmd.Flags().StringVar(&nodeInclude, "include", "", "the node ids that needs to execute the command, split by ',', e.g: '--include=aa,bb,cc', empty means all nodes")
NodeCmd.Flags().StringVar(&nodeExclude, "exclude", "", "the node ids that doesn't need to execute the command, split by ',', e.g: '--exclude=aa,bb,cc', empty means none")
}

var NodeCmd = &cobra.Command{
Use: "node",
Short: "Send some commands to nodes",
Long: `Send a command to nodes and execute it.
Available Commands:
rmold: remove old version(< 0.3.0) node info from mongodb and etcd
sync: sync node info to mongodb
`,
Run: func(cmd *cobra.Command, args []string) {
ea := NewExitAction()
ea.After = func() {
fmt.Println()
cmd.Help()
}
nc, err := cronsun.ToNodeCmd(nodeCmd)
if err != nil {
ea.Exit(err.Error() + ": " + nodeCmd)
}

var include, exclude []string
if len(nodeInclude) > 0 {
include = strings.Split(nodeInclude, spliter)
}
if len(nodeExclude) > 0 {
exclude = strings.Split(nodeExclude, spliter)
}

err = cronsun.PutCsctl(&cronsun.CsctlCmd{
Cmd: nc,
Include: include,
Exclude: exclude,
})
if err != nil {
ea.ExitOnErr(err)
}

fmt.Printf("command[%s] send success\n", nodeCmd)
},
}
7 changes: 5 additions & 2 deletions bin/csctl/cmd/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ var UpgradeCmd = &cobra.Command{
ea.Exit("invalid version number")
}

nodesById := getIPMapper(ea)
nodesById := getIPMapper(ea, prever)
if prever < "0.3.0" {
fmt.Println("upgrading data to version 0.3.0")
if to_0_3_0(ea, nodesById) {
Expand All @@ -48,7 +48,7 @@ var UpgradeCmd = &cobra.Command{
},
}

func getIPMapper(ea *ExitAction) map[string]*cronsun.Node {
func getIPMapper(ea *ExitAction, prever string) map[string]*cronsun.Node {
nodes, err := cronsun.GetNodes()
if err != nil {
ea.Exit("failed to fetch nodes from MongoDB: %s", err.Error())
Expand All @@ -61,6 +61,9 @@ func getIPMapper(ea *ExitAction) map[string]*cronsun.Node {
continue
}

if prever < "0.3.0" {
n.RmOldInfo()
}
ipMapper[n.IP] = n
}

Expand Down
14 changes: 13 additions & 1 deletion bin/web/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
var (
level = flag.Int("l", 0, "log level, -1:debug, 0:info, 1:warn, 2:error")
confFile = flag.String("conf", "conf/files/base.json", "config file path")
network = flag.String("network", "", "network protocol of listen address: ipv4/ipv6, or empty use both")
)

func main() {
Expand All @@ -40,7 +41,7 @@ func main() {
}
web.EnsureJobLogIndex()

l, err := net.Listen("tcp", conf.Config.Web.BindAddr)
l, err := net.Listen(checkNetworkProtocol(*network), conf.Config.Web.BindAddr)
if err != nil {
log.Errorf(err.Error())
return
Expand Down Expand Up @@ -97,3 +98,14 @@ func main() {
event.Emit(event.EXIT, nil)
log.Infof("exit success")
}

func checkNetworkProtocol(p string) string {
switch p {
case "ipv4":
return "tcp4"
case "ipv6":
return "tcp6"
}

return "tcp"
}
5 changes: 4 additions & 1 deletion conf/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,12 @@ type Conf struct {
Proc string // 当前执行任务路径
Cmd string // cmd 路径
Once string // 马上执行任务路径
Csctl string // csctl 发送执行命令的路径
Lock string // job lock 路径
Group string // 节点分组
Noticer string // 通知

PIDFile string
UUIDFile string

Ttl int64 // 节点超时时间,单位秒
Expand Down Expand Up @@ -227,6 +229,7 @@ func (c *Conf) parse(confFile string) error {
c.Proc = cleanKeyPrefix(c.Proc)
c.Cmd = cleanKeyPrefix(c.Cmd)
c.Once = cleanKeyPrefix(c.Once)
c.Csctl = cleanKeyPrefix(c.Csctl)
c.Lock = cleanKeyPrefix(c.Lock)
c.Group = cleanKeyPrefix(c.Group)
c.Noticer = cleanKeyPrefix(c.Noticer)
Expand Down Expand Up @@ -283,7 +286,7 @@ func (c *Conf) reload(confFile string) {
}

// etcd key 选项需要重启
cf.Node, cf.Proc, cf.Cmd, cf.Once, cf.Lock, cf.Group, cf.Noticer = c.Node, c.Proc, c.Cmd, c.Once, c.Lock, c.Group, c.Noticer
cf.Node, cf.Proc, cf.Cmd, cf.Once, cf.Csctl, cf.Lock, cf.Group, cf.Noticer = c.Node, c.Proc, c.Cmd, c.Once, c.Csctl, c.Lock, c.Group, c.Noticer

*c = *cf
log.Infof("config file[%s] reload success", confFile)
Expand Down
4 changes: 4 additions & 0 deletions conf/files/base.json.sample
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"Proc": "/cronsun/proc/",
"Cmd": "/cronsun/cmd/",
"Once": "/cronsun/once/",
"Csctl": "/cronsun/csctl/",
"Lock": "/cronsun/lock/",
"Group": "/cronsun/group/",
"Noticer": "/cronsun/noticer/",
Expand All @@ -21,5 +22,8 @@
"Mgo": "@extend:db.json",
"Mail": "@extend:mail.json",
"Security": "@extend:security.json",
"#comment": "PIDFile and UUIDFile just work for cronnode",
"#PIDFile": "Given a none-empty string to write a pid file to the specialed path, or leave it empty to do nothing",
"PIDFile": "/tmp/cronsun/cronnode_pid",
"UUIDFile": "/etc/cronsun/CRONSUN_UUID"
}
73 changes: 73 additions & 0 deletions csctl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package cronsun

import (
"encoding/json"
"errors"

client "github.com/coreos/etcd/clientv3"

"github.com/shunfei/cronsun/conf"
)

const (
NodeCmdUnknown NodeCmd = iota
NodeCmdRmOld
NodeCmdSync
NodeCmdMax
)

var (
InvalidNodeCmdErr = errors.New("invalid node command")

NodeCmds = []string{
"unknown",
"rmold",
"sync",
}
)

type NodeCmd int

func (cmd NodeCmd) String() string {
if NodeCmdMax <= cmd || cmd <= NodeCmdUnknown {
return "unknown"
}
return NodeCmds[cmd]
}

func ToNodeCmd(cmd string) (NodeCmd, error) {
for nc := NodeCmdUnknown + 1; nc < NodeCmdMax; nc++ {
if cmd == NodeCmds[nc] {
return nc, nil
}
}
return NodeCmdUnknown, InvalidNodeCmdErr
}

type CsctlCmd struct {
// the command send to node
Cmd NodeCmd
// the node ids that needs to execute the command, empty means all node
Include []string
// the node ids that doesn't need to execute the command, empty means none
Exclude []string
}

// 执行 csctl 发送的命令
// 注册到 /cronsun/csctl/<cmd>
func PutCsctl(cmd *CsctlCmd) error {
if NodeCmdMax <= cmd.Cmd || cmd.Cmd <= NodeCmdUnknown {
return InvalidNodeCmdErr
}

params, err := json.Marshal(cmd)
if err != nil {
return err
}
_, err = DefalutClient.Put(conf.Config.Csctl+NodeCmds[cmd.Cmd], string(params))
return err
}

func WatchCsctl() client.WatchChan {
return DefalutClient.Watch(conf.Config.Csctl, client.WithPrefix())
}
21 changes: 13 additions & 8 deletions node.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ const (
type Node struct {
ID string `bson:"_id" json:"id"` // machine id
PID string `bson:"pid" json:"pid"` // 进程 pid
IP string `bson:"ip" json:"ip"` // node ip
PIDFile string `bson:"-" json:"-"`
IP string `bson:"ip" json:"ip"` // node ip
Hostname string `bson:"hostname" json:"hostname"`

Version string `bson:"version" json:"version"`
Expand Down Expand Up @@ -101,7 +102,6 @@ func RemoveNode(query interface{}) error {
return mgoDB.WithC(Coll_Node, func(c *mgo.Collection) error {
return c.Remove(query)
})

}

func ISNodeAlive(id string) (bool, error) {
Expand Down Expand Up @@ -141,19 +141,24 @@ func WatchNode() client.WatchChan {

// On 结点实例启动后,在 mongoDB 中记录存活信息
func (n *Node) On() {
// remove old version(< 0.3.0) node info
mgoDB.RemoveId(Coll_Node, n.IP)

n.Alived, n.Version, n.UpTime = true, Version, time.Now()
if err := mgoDB.Upsert(Coll_Node, bson.M{"_id": n.ID}, n); err != nil {
log.Errorf(err.Error())
}
n.SyncToMgo()
}

// On 结点实例停用后,在 mongoDB 中去掉存活信息
func (n *Node) Down() {
n.Alived, n.DownTime = false, time.Now()
n.SyncToMgo()
}

func (n *Node) SyncToMgo() {
if err := mgoDB.Upsert(Coll_Node, bson.M{"_id": n.ID}, n); err != nil {
log.Errorf(err.Error())
}
}

// RmOldInfo remove old version(< 0.3.0) node info
func (n *Node) RmOldInfo() {
RemoveNode(bson.M{"_id": n.IP})
DefalutClient.Delete(conf.Config.Node + n.IP)
}
32 changes: 32 additions & 0 deletions node/csctl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package node

import (
"encoding/json"

"github.com/shunfei/cronsun"
"github.com/shunfei/cronsun/log"
)

func (n *Node) executCsctlCmd(key, value []byte) error {
cmd := &cronsun.CsctlCmd{}
err := json.Unmarshal(value, cmd)
if err != nil {
log.Warnf("invalid csctl command[%s] value[%s], err: %s", string(key), string(value), err.Error())
return err
}

if cronsun.NodeCmdMax <= cmd.Cmd || cmd.Cmd <= cronsun.NodeCmdUnknown {
log.Warnf("invalid csctl command[%s] value[%s], err: %s", string(key), string(value))
return cronsun.InvalidNodeCmdErr
}

switch cmd.Cmd {
case cronsun.NodeCmdRmOld:
n.Node.RmOldInfo()
case cronsun.NodeCmdSync:
n.Node.SyncToMgo()
}

log.Infof("%s execute csctl command[%s] success", n.String(), cmd.Cmd.String())
return nil
}
Loading

0 comments on commit 9bb382d

Please sign in to comment.