Beispiel #1
0
func (bs *BalancingService) SubscribeEvents() {
	tree_event.ON(tree_event.ON_DOCKER_INIT, func(e *tree_event.Event) {
		var err tree_lib.TreeError
		err.From = tree_lib.FROM_SUBSCRIBE_EVENTS
		if e.LocalVar == nil {
			tree_log.Info(err.From, "Containers list is nil during INIT event")
			return
		}

		for _, c := range e.LocalVar.([]docker.APIContainers) {
			if port, ok := bs.DockerImages[c.Image]; ok {
				var ci *docker.Container
				ci, err.Err = tree_docker.DockerClient.InspectContainer(c.ID)
				if !err.IsNull() {
					continue
				}
				cont_addr := Address{IP: ci.NetworkSettings.IPAddress, Port: port}
				err.Err = bs.AddDestination(cont_addr)
				if !err.IsNull() {
					return
				}
				containerAddressMap[c.ID] = cont_addr
			}
		}
	})
	tree_event.ON(tree_event.ON_DOCKER_CONTAINER_START, func(e *tree_event.Event) {
		var err tree_lib.TreeError
		if e.LocalVar == nil {
			tree_log.Info(log_from_balancer, "Container Info is nil during container Start event")
			return
		}

		ci := e.LocalVar.(*tree_docker.ContainerInfo)
		if port, ok := bs.DockerImages[ci.Image]; ok {
			cont_addr := Address{IP: ci.InspectContainer.NetworkSettings.IPAddress, Port: port}
			err.Err = bs.AddDestination(cont_addr)
			if !err.IsNull() {
				return
			}
			containerAddressMap[ci.ID] = cont_addr
		}
	})

	tree_event.ON(tree_event.ON_DOCKER_CONTAINER_STOP, func(e *tree_event.Event) {
		if e.LocalVar == nil {
			tree_log.Info(log_from_balancer, "Container ID is nil during container Stop event")
			return
		}
		cont_id := e.LocalVar.(string)
		if cont_addr, ok := containerAddressMap[cont_id]; ok {
			bs.DeleteDestination(cont_addr)
			delete(containerAddressMap, cont_id)
			bs.CheckForStopEvent()
		}
	})
}
Beispiel #2
0
func HandleAddCustomEventHandlers(e *tree_event.Event, api_cmd Command) {
	var (
		out          = &WriterCallback{BufferMaxSize: 1024}
		handler_data map[string]interface{}
		err          tree_lib.TreeError
		ev_data      []byte
	)
	err.From = tree_lib.FROM_ADD_CUSTOM_EVENT
	err.Err = ffjson.Unmarshal(api_cmd.Data, &handler_data)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	out.OutCallback = func(data []byte, ended bool) {
		cb_cmd := api_cmd
		cb_cmd.Ended = ended
		cb_cmd.Data = data
		ev_data, err.Err = ffjson.Marshal(cb_cmd)
		if !err.IsNull() {
			tree_log.Error(err.From, err.Error())
			return
		}
		SendCommandCallback(e, ev_data)
	}
	defer out.End()

	event_name := handler_data["name"].(string)
	handles_interfaces := handler_data["handlers"].([]interface{})
	var (
		handles_interfaces_data []byte
		handlers                []custom_event.Handler
	)
	handles_interfaces_data, err.Err = ffjson.Marshal(handles_interfaces)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	err.Err = ffjson.Unmarshal(handles_interfaces_data, &handlers)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	err = custom_event.ON(event_name, handlers...)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
	}
}
func HandleContainerCommand(ev *tree_event.Event, cmd Command) {
	var (
		out        = &WriterCallback{BufferMaxSize: 1024}
		docker_cmd = tree_docker.DockerCmd{}
		err        tree_lib.TreeError
		ev_data    []byte
	)
	err.From = tree_lib.FROM_HANDLE_CONTAINER_COMMAND
	err.Err = ffjson.Unmarshal(cmd.Data, &docker_cmd)
	if !err.IsNull() {
		tree_log.Error(err.From, "unable to unmarshal command data as a docker command -> ", err.Error())
		return
	}
	out.OutCallback = func(data []byte, ended bool) {
		cb_cmd := cmd
		cb_cmd.Ended = ended
		cb_cmd.Data = data
		ev_data, err.Err = ffjson.Marshal(cb_cmd)
		if !err.IsNull() {
			tree_log.Error(err.From, err.Error())
			return
		}
		SendCommandCallback(ev, ev_data)
	}

	defer out.End()

	tree_docker.ContainerCommands(&docker_cmd, out)
}
Beispiel #4
0
// Executing some commands using exec.Command functionality from Go in OS
func HandleExecCommand(e *tree_event.Event, api_cmd Command) {
	var (
		out         = &WriterCallback{BufferMaxSize: 1024}
		cmd_str     = string(api_cmd.Data)
		cmd_options = strings.Split(cmd_str, " ")
		cmd         = exec.Command(cmd_options[0], cmd_options[1:]...)
		err         tree_lib.TreeError
		ev_data     []byte
	)
	err.From = tree_lib.FROM_HANDLE_EXEC_COMMAND
	out.OutCallback = func(data []byte, ended bool) {
		cb_cmd := api_cmd
		cb_cmd.Ended = ended
		cb_cmd.Data = data
		ev_data, err.Err = ffjson.Marshal(cb_cmd)
		if !err.IsNull() {
			tree_log.Error(err.From, err.Error())
			return
		}
		SendCommandCallback(e, ev_data)
	}

	defer out.End()

	cmd.Stdout = out
	cmd.Stderr = out
	err.Err = cmd.Run()
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
	}
}
Beispiel #5
0
func HandleNodeCommand(cmd *cobra.Command, args []string) {
	var (
		name string
		err  tree_lib.TreeError
	)
	err.From = tree_lib.FROM_HANDLE_NODE_COMMAND
	name, err.Err = cmd.Flags().GetString("set-name")
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
	}

	// If we have set-name flag then we just setting current_node in database and exiting
	if len(name) > 0 {
		tree_db.Set(tree_db.DB_RANDOM, []byte("current_node"), []byte(name))
		return
	}
	daemon := false
	daemon, err.Err = cmd.Flags().GetBool("daemon")
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	if daemon {
		cmd := exec.Command("/bin/sh", "-c", fmt.Sprintf("%s node > %s 2>&1 &", os.Args[0], tree_log.LogFile))
		err.Err = cmd.Run()
		if !err.IsNull() {
			log.Fatal(err.Err)
		}
		return
	}

	name, err.Err = cmd.Flags().GetString("name")
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	if len(name) == 0 {
		current_node_byte, err := tree_db.Get(tree_db.DB_RANDOM, []byte("current_node"))
		if !err.IsNull() {
			tree_log.Error(err.From, "Getting current node name from Random database, ", err.Error())
			return
		}
		if len(current_node_byte) == 0 {
			fmt.Println("Name is important for the first time run")
			return
		}
	} else {
		err = tree_node.SetCurrentNode(name)
		if !err.IsNull() {
			tree_log.Error(err.From, err.Error())
			return
		}
	}

	tree_node.Start()
}
Beispiel #6
0
func HandleUpdateCommand(ev *tree_event.Event, cmd Command) {
	var (
		data Command
		info node_info.NodeInfo
		err  tree_lib.TreeError
	)
	err.From = tree_lib.FROM_HANDLE_UPDATE_COMMAND
	err.Err = ffjson.Unmarshal(ev.Data, &data)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
	}
	err.Err = ffjson.Unmarshal(data.Data, &info)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
	}
	UpdateNodeChange(info)
	SendCommandCallback(ev, ev.Data)
}
Beispiel #7
0
func TriggerFromData(data []byte) {
	var (
		e   = new(Event)
		err tree_lib.TreeError
	)
	err.From = tree_lib.FROM_TRIGGER_FROM_DATA
	err.Err = ffjson.Unmarshal(data, e)
	if !err.IsNull() {
		tree_log.Error(log_from_event, err.Error())
		return
	}
	Trigger(e)
}
Beispiel #8
0
func HandleApiCommand(cmd_data []byte, api_out io.Writer) {
	var (
		err tree_lib.TreeError
		cmd DockerCmd
	)
	err.From = tree_lib.FROM_HANDLE_API_COMMAND
	err.Err = ffjson.Unmarshal(cmd_data, &cmd)
	if !err.IsNull() {
		writeOutput(api_out, true, fmt.Sprintf("--- Unable to parse Container command data: %s", string(cmd_data)), map[string]string{})
		return
	}

	ContainerCommands(&cmd, api_out)
	fmt.Println(string(cmd_data))
}
Beispiel #9
0
func ContainerCommands(cmd *DockerCmd, out io.Writer) {
	var (
		err tree_lib.TreeError
	)
	err.From = tree_lib.FROM_CONTAINER_COMMANDS
	switch cmd.Command {
	case COMMAND_DOCKER_CONTAINER_CREATE, COMMAND_DOCKER_CONTAINER_START:
		{
			var (
				cont       *docker.Container
				conf       = &docker.Config{}
				host_conf  = &docker.HostConfig{}
				cont_count int
				start_cont = false
			)
			if cc, ok := cmd.Content["count"]; ok {
				cont_count, err.Err = strconv.Atoi(cc)
				if !err.IsNull() {
					writeOutput(out, true, fmt.Sprintf("--- Invalid number given for Containers count: %s", cc), cmd.Content)
					return
				}
			} else {
				cont_count = 1
			}

			if run_cmd, ok := cmd.Content["cmd"]; ok {
				conf.Cmd = []string{run_cmd}
			}

			if img, ok := cmd.Content["image"]; ok {
				conf.Image = img
			}

			// By default we just don't need any output
			conf.AttachStderr = false
			conf.AttachStdin = false
			conf.AttachStdout = false

			if cs, ok := cmd.Content["cpu"]; ok {
				var cs_int int
				cs_int, err.Err = strconv.Atoi(cs)
				if !err.IsNull() {
					writeOutput(out, true, fmt.Sprintf("--- Invalid number given for CPU Shares: %s", cs), cmd.Content)
					return
				}
				host_conf.CPUShares = int64(cs_int)
			}

			if ram, ok := cmd.Content["ram"]; ok {
				var ram_int int
				ram_int, err.Err = strconv.Atoi(ram)
				if !err.IsNull() {
					writeOutput(out, true, fmt.Sprintf("--- Invalid number given for RAM: %s", ram), cmd.Content)
					return
				}
				host_conf.Memory = int64(ram_int)
			}

			if st, ok := cmd.Content["start"]; ok {
				switch st {
				case "yes", "y", "true", "t":
					start_cont = true
				case "no", "n", "false", "f":
					start_cont = false
				}
			}

			// If we just want to start container by ID just running it and returning
			if cmd.Command == COMMAND_DOCKER_CONTAINER_START {
				if cid, ok := cmd.Content["container"]; ok {
					err.Err = DockerClient.StartContainer(cid, host_conf)
					if !err.IsNull() {
						writeOutput(out, true, fmt.Sprintf("--- Unable to start container: %s", err.Error()), cmd.Content)
						return
					}
					writeOutput(out, false, fmt.Sprintf("Container Started \n  Container -> %s\n", cid), cmd.Content)
				}
				return
			}

			for i := 0; i < cont_count; i++ {
				cont, err.Err = DockerClient.CreateContainer(docker.CreateContainerOptions{
					Config:     conf,
					HostConfig: host_conf,
				})

				if !err.IsNull() {
					writeOutput(out, true, fmt.Sprintf("--- Container creation error: %s", err.Error()), cmd.Content)
					return
				}

				writeOutput(out, false, fmt.Sprintf("Container Created \n  ID -> %s\n  Name -> %s\n", cont.ID, cont.Name), cmd.Content)
				if start_cont {
					err.Err = DockerClient.StartContainer(cont.ID, host_conf)
					if !err.IsNull() {
						writeOutput(out, true, fmt.Sprintf("--- Unable to start container: %s", err.Error()), cmd.Content)
						return
					}
					writeOutput(out, false, fmt.Sprintf("Container Started \n  Name -> %s\n", cont.Name), cmd.Content)
				}
			}
		}
	case COMMAND_DOCKER_CONTAINER_PAUSE:
		{
			if cid, ok := cmd.Content["container"]; ok {
				err.Err = DockerClient.PauseContainer(cid)
				if !err.IsNull() {
					writeOutput(out, true, fmt.Sprintf("--- Unable to pause container: %s", err.Error()), cmd.Content)
					return
				}
				writeOutput(out, false, fmt.Sprintf("Container Paused \n  Container -> %s\n", cid), cmd.Content)
			}
		}
	case COMMAND_DOCKER_CONTAINER_RESUME:
		{
			if cid, ok := cmd.Content["container"]; ok {
				err.Err = DockerClient.UnpauseContainer(cid)
				if !err.IsNull() {
					writeOutput(out, true, fmt.Sprintf("--- Unable to Resume container: %s", err.Error()), cmd.Content)
					return
				}
				writeOutput(out, false, fmt.Sprintf("Container Resumed \n  Container -> %s\n", cid), cmd.Content)
			}
		}
	case COMMAND_DOCKER_CONTAINER_DELETE:
		{
			if cid, ok := cmd.Content["container"]; ok {
				DockerClient.StopContainer(cid, 0) // Stopping container if it exists
				err.Err = DockerClient.RemoveContainer(docker.RemoveContainerOptions{ID: cid, Force: true})
				if !err.IsNull() {
					writeOutput(out, true, fmt.Sprintf("--- Unable to Resume container: %s", err.Error()), cmd.Content)
					return
				}
				writeOutput(out, false, fmt.Sprintf("Container Resumed \n  Container -> %s\n", cid), cmd.Content)
			}
		}
	case COMMAND_DOCKER_CONTAINER_STOP:
		{
			var (
				stop_timeout = uint(0)
				st_int       int
			)

			if tm, ok := cmd.Content["timeout"]; ok {
				st_int, err.Err = strconv.Atoi(tm)
				if !err.IsNull() {
					writeOutput(out, true, fmt.Sprintf("--- Invalid number given for Timeout: %s", tm), cmd.Content)
					return
				}
				stop_timeout = uint(st_int)
			}

			if cid, ok := cmd.Content["container"]; ok {
				err.Err = DockerClient.StopContainer(cid, stop_timeout)
				if !err.IsNull() {
					writeOutput(out, true, fmt.Sprintf("--- Unable to Stop container: %s", err.Error()), cmd.Content)
					return
				}
				writeOutput(out, false, fmt.Sprintf("Container Stopped \n  Container -> %s\n", cid), cmd.Content)
			}
		}

	case COMMAND_DOCKER_IMAGE_PULL:
		{
			var (
				registry           string
				repository         string
				tag                string
				image              string
				img_repo           string
				registery_username string
				registery_email    string
				registery_passord  string
				registery_address  string
			)

			if r, ok := cmd.Content["registry"]; ok {
				registry = r
			} else {
				registry = ""
			}

			if im, ok := cmd.Content["image"]; ok {
				image = im
			} else {
				writeOutput(out, true, "--- Image Name is required during image pull process", cmd.Content)
				return
			}

			str_split := strings.Split(image, ":")
			if len(str_split) != 2 {
				writeOutput(out, true, "--- Please Specify image tag name with this format <repository>:<tag>", cmd.Content)
				return
			}

			repository = str_split[0]
			tag = str_split[1]
			if len(registry) > 0 {
				img_repo = fmt.Sprintf("%s/%s", registry, repository)
			} else {
				img_repo = repository
			}

			// Getting Registery authentication data
			if ru, ok := cmd.Content["registry_username"]; ok {
				registery_username = ru
			}
			if rp, ok := cmd.Content["registry_password"]; ok {
				registery_passord = rp
			}
			if rem, ok := cmd.Content["registry_email"]; ok {
				registery_email = rem
			}
			if raddr, ok := cmd.Content["registry_address"]; ok {
				registery_address = raddr
			}

			err.Err = DockerClient.PullImage(docker.PullImageOptions{
				Registry:     registry,
				Repository:   img_repo,
				Tag:          tag,
				OutputStream: nil,
			}, docker.AuthConfiguration{
				Username:      registery_username,
				Email:         registery_email,
				Password:      registery_passord,
				ServerAddress: registery_address,
			})

			if !err.IsNull() {
				writeOutput(out, true, fmt.Sprintf("--- Pulling image error: %s", err.Error()), cmd.Content)
				return
			}

			err.Err = DockerClient.TagImage(fmt.Sprintf("%s:%s", img_repo, tag), docker.TagImageOptions{
				Repo:  repository,
				Tag:   tag,
				Force: true,
			})

			if !err.IsNull() {
				writeOutput(out, true, fmt.Sprintf("--- Error Renaming pulled image %s : %s", fmt.Sprintf("%s:%s", img_repo, tag), err.Error()), cmd.Content)
				DockerClient.RemoveImageExtended(fmt.Sprintf("%s:%s", img_repo, tag), docker.RemoveImageOptions{Force: true})
				return
			}

			DockerClient.RemoveImage(fmt.Sprintf("%s:%s", img_repo, tag))
			writeOutput(out, false, fmt.Sprintf("Image Created %s", image), cmd.Content)
		}
	case COMMAND_DOCKER_IMAGE_DELETE:
		{
			var (
				image string
				force = false
			)

			if im, ok := cmd.Content["image"]; ok {
				image = im
			} else {
				writeOutput(out, true, "--- For Deleting image you need to specifi image name", cmd.Content)
				return
			}

			if f, ok := cmd.Content["force"]; ok {
				switch f {
				case "yes", "y", "true", "t":
					force = true
				case "no", "n", "false", "f":
					force = false
				}
			}

			err.Err = DockerClient.RemoveImageExtended(image, docker.RemoveImageOptions{Force: force})

			if !err.IsNull() {
				writeOutput(out, true, fmt.Sprintf("--- Error Deleting image %s : %s", image, err.Error()), cmd.Content)
				return
			}

			writeOutput(out, false, fmt.Sprintf("Image deleted %s", image), cmd.Content)
		}

	case COMMAND_DOCKER_CONTAINER_INSPECT:
		{
			var (
				cont_id   string
				container = make(map[string]interface{})
			)

			if cid, ok := cmd.Content["container"]; ok {
				cont_id = cid
			} else {
				writeOutput(out, true, "--- Container Name or ID is required during inspecting", cmd.Content)
				return
			}

			container[cont_id], err.Err = DockerClient.InspectContainer(cont_id)
			writeDcOutput(out, DockerCmdOutput{
				Error:    false,
				Message:  "Container Inspected Successfully",
				Data:     cmd.Content,
				DataList: container,
			})
		}

	case COMMAND_DOCKER_CONTAINER_LIST:
		{
			var (
				all        = false
				containers []docker.APIContainers
				w_list     = make(map[string]interface{})
			)

			if a, ok := cmd.Content["all"]; ok {
				switch a {
				case "yes", "y", "true", "t":
					all = true
				case "no", "n", "false", "f":
					all = false
				}
			}

			containers, err.Err = DockerClient.ListContainers(docker.ListContainersOptions{All: all})
			if !err.IsNull() {
				writeOutput(out, true, "--- Error Getting Container list", cmd.Content)
				return
			}

			for _, c := range containers {
				w_list[c.ID], err.Err = DockerClient.InspectContainer(c.ID)
				if !err.IsNull() {
					writeDcOutput(out, DockerCmdOutput{
						Error:    true,
						Message:  fmt.Sprintf("--- Error Inspecting container %s", c.ID),
						Data:     cmd.Content,
						DataList: w_list,
					})
				}
			}

			writeDcOutput(out, DockerCmdOutput{
				Error:    false,
				Message:  "Containers list fetched successfully",
				Data:     cmd.Content,
				DataList: w_list,
			})
		}
	case COMMAND_DOCKER_IMAGE_LIST:
		{
			var (
				all    = false
				images []docker.APIImages
				w_list = make(map[string]interface{})
			)

			if a, ok := cmd.Content["all"]; ok {
				switch a {
				case "yes", "y", "true", "t":
					all = true
				case "no", "n", "false", "f":
					all = false
				}
			}

			images, err.Err = DockerClient.ListImages(docker.ListImagesOptions{All: all})
			if !err.IsNull() {
				writeOutput(out, true, "--- Error Getting Image list", cmd.Content)
				return
			}

			for _, im := range images {
				w_list[im.ID], err.Err = DockerClient.InspectImage(im.ID)
				if !err.IsNull() {
					writeDcOutput(out, DockerCmdOutput{
						Error:    true,
						Message:  fmt.Sprintf("--- Error Inspecting image %s", im.ID),
						Data:     cmd.Content,
						DataList: w_list,
					})
				}
			}

			writeDcOutput(out, DockerCmdOutput{
				Error:    false,
				Message:  "Images list fetched successfully",
				Data:     cmd.Content,
				DataList: w_list,
			})
		}
	}
}
Beispiel #10
0
func CompileConfig(cmd *cobra.Command, args []string) {
	var (
		files         []string
		conf_type     string
		out_file      string
		paths         []string
		files_in_path []string
		err           tree_lib.TreeError
	)
	err.From = tree_lib.FROM_COMPILE_CONFIG
	files, err.Err = cmd.Flags().GetStringSlice("files")
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	conf_type, err.Err = cmd.Flags().GetString("type")
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	out_file, err.Err = cmd.Flags().GetString("out")
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}
	if _, err.Err = os.Stat(out_file); err.Err == nil {
		err.Err = os.Remove(out_file)
		if !err.IsNull() {
			tree_log.Error(err.From, err.Error())
		}
	}

	paths, err.Err = cmd.Flags().GetStringSlice("path")
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}
	if len(paths) > 0 {
		files_in_path, err = PathFiles(conf_type, paths)
		if !err.IsNull() {
			tree_log.Error(err.From, err.Error())
			return
		}
		for _, a := range files_in_path {
			files = append(files, a)
		}
	}
	if len(files) > 0 {
		err = ParseFiles(conf_type, files...)
		if !err.IsNull() {
			tree_log.Error(err.From, err.Error())
			return
		}
	}

	DBFromConfig()
	err = tree_db.DumpDBPath(out_file)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}
	// Deleting database dir from console part
	err.Err = os.RemoveAll(tree_db.DB_DIR)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
	}
}
Beispiel #11
0
func handle_api_or_parent_connection(conn *net.TCPConn) {
	defer conn.Close() // Connection should be closed, after return this function
	var (
		err            tree_lib.TreeError
		msg_data       []byte
		info_data      []byte
		conn_name      string
		is_api         = false
		conn_node_info node_info.NodeInfo
		api_val        *big.Int
	)
	err.From = tree_lib.FROM_HANDLE_API_OR_PARENT_CONNECTION
	// Making basic handshake to check the API validation
	// Connected Parent receiving name of the child(current node) and checking is it valid or not
	// if it is valid name then parent sending his name as an answer
	// otherwise it sending CLOSE_CONNECTION_MARK and closing connection

	info_data, err.Err = ffjson.Marshal(node_info.CurrentNodeInfo)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	_, err.Err = tree_lib.SendMessage(info_data, conn)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	info_data, err = tree_lib.ReadMessage(conn)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	conn_name = string(info_data)
	if conn_name == CLOSE_CONNECTION_MARK {
		tree_log.Info(err.From, "Connection closed by parent node. Bad tree network handshake ! ", "Parent Addr: ", conn.RemoteAddr().String())
		return
	}

	err.Err = ffjson.Unmarshal(info_data, &conn_node_info)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	if strings.Contains(conn_node_info.Name, tree_api.API_NAME_PREFIX) {
		api_val = big.NewInt(conn_node_info.Value)
		api_connections[api_val] = conn
		is_api = true
	} else {
		// TODO: Think about conn_node_info if we need to more checking for parent node info
		parentConnection = conn
	}

	if is_api {
		tree_event.TriggerWithData(tree_event.ON_API_CONNECTED, info_data)
	} else {
		tree_event.TriggerWithData(tree_event.ON_PARENT_CONNECTED, info_data)
	}

	// Listening parent messages
	for {
		msg_data, err = tree_lib.ReadMessage(conn)
		if !err.IsNull() {
			tree_log.Error(err.From, " reading data from -> ", conn_name, " ", err.Error())
			break
		}

		// Handling message events
		handle_message(is_api, true, msg_data)
	}

	if is_api {
		api_connections[api_val] = nil
		delete(api_connections, api_val)
		tree_event.TriggerWithData(tree_event.ON_API_DISCONNECTED, info_data)
	} else {
		parentConnection = nil
		tree_event.TriggerWithData(tree_event.ON_PARENT_DISCONNECTED, info_data)
	}
}
Beispiel #12
0
func HandleListCommand(ev *tree_event.Event, cmd Command) {
	var (
		info           = make(map[string]node_info.NodeInfo)
		data           []byte
		ev_data        Command
		nodes          []string
		nodes_in_group []string
		nodes_in_tag   []string
		err            tree_lib.TreeError
		infos          Info
	)
	err.From = tree_lib.FROM_HANDLE_LIST_COMMAND
	err.Err = ffjson.Unmarshal(ev.Data, &ev_data)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}
	err.Err = ffjson.Unmarshal(ev_data.Data, &infos)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}
	nodes = infos.Target
	for _, g := range infos.Group {
		nodes_in_group, err = tree_db.GetGroupNodes(g)
		if !err.IsNull() {
			tree_log.Error(err.From, err.Error())
			return
		}
		for _, n := range nodes_in_group {
			nodes = append(nodes, n)
		}
	}
	for _, t := range infos.Tag {
		nodes_in_tag, err = tree_db.GetNodesByTagName(t)
		if !err.IsNull() {
			tree_log.Error(err.From, "getting Tags", err.Error())
			return
		}
		for _, n := range nodes_in_tag {
			nodes = append(nodes, n)
		}
	}
	for _, n := range nodes {
		info[n], err = tree_db.GetNodeInfo(n)
		if !err.IsNull() {
			tree_log.Error(err.From, err.Error())
			return
		}
	}
	cb_cmd := cmd
	cb_cmd.Data, err.Err = ffjson.Marshal(info)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}
	data, err.Err = ffjson.Marshal(cb_cmd)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}

	SendCommandCallback(ev, data)
}
Beispiel #13
0
func init() {
	var err tree_lib.TreeError
	err.From = tree_lib.FROM_INIT
	tree_db, err.Err = bolt.Open(DB_DIR, 0600, nil)
	if !err.IsNull() {
		tree_log.Error(log_from_db, " unable to open database", err.Error())
		tree_db = nil
		os.Exit(1) // Without database we can't keep and share configurations, so program should be exited
	}

	// creating Buckets in database
	tree_db.Update(func(tx *bolt.Tx) (err error) {
		// Setting databases
		for _, d := range [][]byte{DB_NODE, DB_BALANCER, DB_RANDOM, DB_GROUP, DB_TAG, DB_RELATIONS, DB_REGISTRY, DB_EVENT} {
			_, err = tx.CreateBucketIfNotExists(d)
			if err != nil {
				return err
			}
		}
		return nil
	})

	// Handling node change event
	tree_event.ON(tree_event.ON_UPDATE_NODE_INFO, func(e *tree_event.Event) {
		var (
			info    node_info.NodeInfo
			ev_info node_info.NodeInfo
			names   []string
			data    []byte
			mark    bool
		)
		err.Err = ffjson.Unmarshal(e.Data, &ev_info)
		if !err.IsNull() {
			tree_log.Error(err.From, err.Error())
			return
		}
		info, err = GetNodeInfo(ev_info.Name)
		if !err.IsNull() {
			tree_log.Error(err.From, err.Error())
			return
		}
		if len(info.Name) > 0 {
			err = DeleteNodeFromHisGroups(info.Name)
			if !err.IsNull() {
				tree_log.Error(err.From, err.Error())
				return
			}
			err = DeleteNodeFromHisTags(info.Name)
			if !err.IsNull() {
				tree_log.Error(err.From, err.Error())
				return
			}
			if len(ev_info.TreeIp) > 0 {
				info.TreeIp = ev_info.TreeIp
				mark = true
			}
			if ev_info.TreePort != -1 {
				info.TreePort = ev_info.TreePort
				mark = true
			}
			if len(ev_info.Childs[0]) > 0 {
				info.Childs = append(info.Childs, ev_info.Childs[0])
			}
			if len(ev_info.Childs[1]) > 0 {
				if g, ok := tree_lib.ArrayContains(info.Childs, ev_info.Childs[1]); ok {
					info.Childs = info.Childs[:g+copy(info.Childs[g:], info.Childs[g+1:])]
				}
			}
			if len(ev_info.Groups[0]) > 0 {
				info.Groups = append(info.Groups, ev_info.Groups[0])
			}
			if len(ev_info.Groups[1]) > 0 {
				if g, ok := tree_lib.ArrayContains(info.Groups, ev_info.Groups[1]); ok {
					info.Groups = info.Groups[:g+copy(info.Groups[g:], info.Groups[g+1:])]
				}
			}
			if len(ev_info.Tags[0]) > 0 {
				info.Tags = append(info.Tags, ev_info.Tags[0])
			}
			if len(ev_info.Tags[1]) > 0 {
				if g, ok := tree_lib.ArrayContains(info.Tags, ev_info.Tags[1]); ok {
					info.Tags = info.Tags[:g+copy(info.Tags[g:], info.Tags[g+1:])]
				}
			}
			data, err.Err = ffjson.Marshal(info)
			if !err.IsNull() {
				tree_log.Error(err.From, err.Error())
				return
			}
			err = Set(DB_NODE, []byte(ev_info.Name), data)
			if !err.IsNull() {
				tree_log.Error(err.From, err.Error())
				return
			}
			names, err = ListNodeNames()
			if !err.IsNull() {
				tree_log.Error(err.From, err.Error())
				return
			}

			err = AddNodeToHisGroups(info.Name)
			if !err.IsNull() {
				tree_log.Error(err.From, err.Error())
				return
			}
			err = AddNodeToHisTags(info.Name)
			if !err.IsNull() {
				tree_log.Error(err.From, err.Error())
				return
			}
			for _, n := range names {
				err = SetRelations(n)
				if !err.IsNull() {
					tree_log.Error(err.From, err.Error())
					return
				}
			}
			if node_info.CurrentNodeInfo.Name == ev_info.Name && mark {
				var e1 tree_event.Event
				e1.Name = tree_event.ON_RESTART_NODE
				tree_event.Trigger(&e1)
			}
		} else {
			err = Set(DB_NODE, []byte(ev_info.Name), e.Data)
			if !err.IsNull() {
				tree_log.Error(err.From, err.Error())
				return
			}
			names, err = ListNodeNames()
			if !err.IsNull() {
				tree_log.Error(err.From, err.Error())
				return
			}
			err = AddNodeToHisGroups(ev_info.Name)
			if !err.IsNull() {
				tree_log.Error(err.From, err.Error())
				return
			}
			err = AddNodeToHisTags(ev_info.Name)
			if !err.IsNull() {
				tree_log.Error(err.From, err.Error())
				return
			}
			for _, n := range names {
				err = SetRelations(n)
				if !err.IsNull() {
					tree_log.Error(err.From, err.Error())
					return
				}
			}
			if node_info.CurrentNodeInfo.Name == ev_info.Name {
				var e1 *tree_event.Event
				e1.Name = tree_event.ON_RESTART_NODE
				tree_event.Trigger(e1)
			}
		}
	})

	// Closing database before program will be exited
	// Just in case if program exiting force or we don't want to make dead lock
	tree_event.ON(tree_event.ON_PROGRAM_EXIT, func(e *tree_event.Event) {
		CloseDB()
	})
}
Beispiel #14
0
func init() {
	// This event will be triggered from Node, when API client will send some command to implement
	tree_event.ON(tree_event.ON_API_COMMAND, func(ev *tree_event.Event) {
		var err tree_lib.TreeError
		err.From = tree_lib.FROM_INIT
		cmd := Command{}
		err.Err = ffjson.Unmarshal(ev.Data, &cmd)
		if !err.IsNull() {
			tree_log.Error(err.From, "unable to unmarshal event data as a command -> ", err.Error())
			return
		}

		switch cmd.CommandType {
		case COMMAND_EXEC:
			{
				HandleExecCommand(ev, cmd)
			}
		case COMMAND_LIST:
			{
				HandleListCommand(ev, cmd)
			}
		case COMMAND_UPDATE:
			{
				HandleUpdateCommand(ev, cmd)
			}
		case COMMAND_CONTAINER:
			{
				HandleContainerCommand(ev, cmd)
			}
		case COMMAND_ADD_CUSTOM_EVENT:
			{
				HandleAddCustomEventHandlers(ev, cmd)
			}
		case COMMAND_TRIGGER_EVENT:
			{
				HandleTriggerCustomEvent(ev, cmd)
			}
		}
	})

	// This event will be triggered from API client when Node will give callback for specific commands
	tree_event.ON(tree_event.ON_API_COMMAND_CALLBACK, func(ev *tree_event.Event) {
		var err tree_lib.TreeError
		err.From = tree_lib.FROM_INIT
		cmd := Command{}
		err.Err = ffjson.Unmarshal(ev.Data, &cmd)
		if !err.IsNull() {
			tree_log.Error(err.From, "unable to unmarshal event data as a command -> ", err.Error())
			return
		}

		if cb, ok := subscribed_command_callbacks[cmd.ID]; ok && cb.f != nil {
			if !cb.f(ev, cmd) {
				// TODO: Maybe we need mutex to lock deleting process
				delete(subscribed_command_callbacks, cmd.ID)
				if cb.c != nil {
					cb.c <- true // Ending wait chanel in send command
				}
			}
		}
	})
}
Beispiel #15
0
func ListInfos(cmd *cobra.Command, args []string) {
	var (
		err     tree_lib.TreeError
		node    string
		targets []string
		groups  []string
		tags    []string
		info    tree_api.Info
	)
	err.From = tree_lib.FROM_LIST_INFOS
	node, err.Err = cmd.Flags().GetString("node")
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}
	targets, err.Err = cmd.Flags().GetStringSlice("target")
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}
	groups, err.Err = cmd.Flags().GetStringSlice("group")
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}
	tags, err.Err = cmd.Flags().GetStringSlice("tag")
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}
	if !tree_api.API_INIT(node) {
		fmt.Println("Unable to init api client")
		fmt.Println("Exiting ...")
		return
	}
	var (
		api_cmd = tree_api.Command{}
		wait    = make(chan bool)
	)
	info.Group = groups
	info.Target = targets
	info.Tag = tags
	api_cmd.Data, err.Err = ffjson.Marshal(info)
	if !err.IsNull() {
		tree_log.Error(err.From, err.Error())
		return
	}
	api_cmd.ID = tree_lib.RandomString(20)
	api_cmd.CommandType = tree_api.COMMAND_LIST

	tree_event.ON(tree_event.ON_CHILD_CONNECTED, func(ev *tree_event.Event) {
		path := &tree_graph.Path{From: node, Nodes: []string{node}}

		tree_api.SendCommand(&api_cmd, path, func(e *tree_event.Event, c tree_api.Command) bool {
			var (
				err  tree_lib.TreeError
				info = make(map[string]node_info.NodeInfo)
			)
			err.Err = ffjson.Unmarshal(c.Data, &info)
			if !err.IsNull() {
				tree_log.Error(err.From, err.Error())
				return false
			}
			for _, a := range info {
				fmt.Println("name: ", a.Name, ", Adress: ", a.TreeIp, ":", a.TreePort, ", Value: ", a.Value)
				fmt.Println("groups:", a.Groups)
				fmt.Println("tags:", a.Tags)
				fmt.Println("childs", a.Childs)
			}
			return false
		})
		wait <- true
	})
	<-wait
}