func main() { host := oswrapper.Getopt("HOST", "127.0.0.1") etcdPort := oswrapper.Getopt("ETCD_PORT", "4001") etcdCtlPeers := oswrapper.Getopt("ETCD_PEERS", "127.0.0.1:"+etcdPort) etcdURL := etcd.GetHTTPEtcdUrls(host+":"+etcdPort, etcdCtlPeers) etcdClient := etcd.NewClient(etcdURL) etcd.Mkdir(etcdClient, etcdPath) log.Infof("boot version [%v]", version.Version) log.Info("zookeeper: starting...") zookeeper.CheckZkMappingInFleet(etcdPath, etcdClient, etcdURL) // we need to write the file /opt/zookeeper-data/data/myid with the id of this node os.MkdirAll("/opt/zookeeper-data/data", 0640) zkID := etcd.Get(etcdClient, etcdPath+"/"+host+"/id") ioutil.WriteFile("/opt/zookeeper-data/data/myid", []byte(zkID), 0640) zkServer := &zookeeper.ZkServer{ Stdout: os.Stdout, Stderr: os.Stderr, } signal.Notify(signalChan, syscall.SIGHUP, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM, syscall.SIGQUIT, os.Interrupt, ) // Wait for a signal and exit exitChan := make(chan int) go func() { for { s := <-signalChan log.Debugf("Signal received: %v", s) switch s { case syscall.SIGTERM: exitChan <- 0 case syscall.SIGQUIT: exitChan <- 0 case syscall.SIGKILL: exitChan <- 1 default: exitChan <- 1 } } }() // wait for confd to run once and install initial templates confd.WaitForInitialConf(getConfdNodes(host, etcdCtlPeers, 4001), 10*time.Second) params := make(map[string]string) params["HOST"] = host if log.Level.String() == "debug" { params["DEBUG"] = "true" } err := oswrapper.RunScript("pkg/boot/zookeeper/bash/add-node.bash", params, bindata.Asset) if err != nil { log.Printf("command finished with error: %v", err) } if err := zkServer.Start(); err != nil { panic(err) } log.Info("zookeeper: running...") go func() { log.Debugf("starting pprof http server in port 6060") http.ListenAndServe("localhost:6060", nil) }() code := <-exitChan log.Debugf("execution terminated with exit code %v", code) log.Debugf("executing pre shutdown script") err = oswrapper.RunScript("pkg/boot/zookeeper/bash/remove-node.bash", params, bindata.Asset) if err != nil { log.Printf("command finished with error: %v", err) } log.Info("stopping zookeeper node") zkServer.Stop() }
func start(currentBoot *types.CurrentBoot) { log.Info("starting component...") log.Debug("creating required etcd directories") for _, key := range component.MkdirsEtcd() { etcd.Mkdir(currentBoot.EtcdClient, key) } log.Debug("setting default etcd values") for key, value := range component.EtcdDefaults() { etcd.SetDefault(currentBoot.EtcdClient, key, value) } // component.PreBoot(currentBoot) initial, daemon := component.UseConfd() if initial { // wait for confd to run once and install initial templates log.Debug("waiting for initial confd configuration") confd.WaitForInitialConf(currentBoot.ConfdNodes, currentBoot.Timeout) } log.Debug("running preboot code") component.PreBoot(currentBoot) log.Debug("running pre boot scripts") preBootScripts := component.PreBootScripts(currentBoot) runAllScripts(signalChan, preBootScripts) if daemon { // spawn confd in the background to update services based on etcd changes log.Debug("launching confd") go confd.Launch(signalChan, currentBoot.ConfdNodes) } log.Debug("running boot daemons") servicesToStart := component.BootDaemons(currentBoot) for _, daemon := range servicesToStart { go oswrapper.RunProcessAsDaemon(signalChan, daemon.Command, daemon.Args) } // if the returned ips contains the value contained in $HOST it means // that we are running docker with --net=host ipToListen := "0.0.0.0" netIfaces := net.GetNetworkInterfaces() for _, iface := range netIfaces { if strings.Index(iface.IP, currentBoot.Host.String()) > -1 { ipToListen = currentBoot.Host.String() break } } portsToWaitFor := component.WaitForPorts() log.Debugf("waiting for a service in the port %v in ip %v", portsToWaitFor, ipToListen) for _, portToWait := range portsToWaitFor { if portToWait > 0 { err := net.WaitForPort("tcp", ipToListen, portToWait, timeout) if err != nil { log.Errorf("error waiting for port %v using ip %v: %v", portToWait, ipToListen, err) signalChan <- syscall.SIGINT } } } time.Sleep(60 * time.Second) // we only publish the service in etcd if the port if > 0 if currentBoot.Port > 0 { log.Debug("starting periodic publication in etcd...") log.Debugf("etcd publication path %s, host %s and port %v", currentBoot.EtcdPath, currentBoot.Host, currentBoot.Port) go etcd.PublishService(currentBoot.EtcdClient, currentBoot.EtcdPath+"/"+currentBoot.Host.String(), currentBoot.Host.String(), currentBoot.Port, uint64(ttl.Seconds()), timeout) // Wait for the first publication time.Sleep(timeout / 2) } log.Debug("running post boot scripts") postBootScripts := component.PostBootScripts(currentBoot) runAllScripts(signalChan, postBootScripts) log.Debug("checking for cron tasks...") crons := component.ScheduleTasks(currentBoot) _cron := cron.New() for _, cronTask := range crons { _cron.AddFunc(cronTask.Frequency, cronTask.Code) } _cron.Start() component.PostBoot(currentBoot) }