hosts file
This commit is contained in:
parent
6adfdfa634
commit
0e3c8081c6
5 changed files with 287 additions and 153 deletions
71
container.go
Normal file
71
container.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
type Containers struct {
|
||||
Containers []Container `json:"containers"`
|
||||
}
|
||||
|
||||
type Container struct {
|
||||
Name string `json:"names"`
|
||||
Port int `json:"port"`
|
||||
IP string `json:"ip"`
|
||||
Image string `json:"image"`
|
||||
ID string `json:"id"`
|
||||
Status string `json:"status"`
|
||||
State string `json:"state"`
|
||||
}
|
||||
|
||||
type Models struct {
|
||||
Models []Model `json:"models"`
|
||||
}
|
||||
|
||||
func (c *Containers) Add(ctr Container) {
|
||||
c.Containers = append(c.Containers, ctr)
|
||||
}
|
||||
|
||||
func (c *Containers) Adds(ctrs Containers) {
|
||||
c.Containers = append(c.Containers, ctrs.Containers...)
|
||||
}
|
||||
|
||||
func get_ollama_containers(host Host, all bool) Containers {
|
||||
|
||||
ctr_list := Containers{}
|
||||
|
||||
cli, err := client.NewClientWithOpts(client.WithHost(fmt.Sprintf("tcp://%s:%s", host.IP, host.Port)))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return ctr_list
|
||||
}
|
||||
defer cli.Close()
|
||||
|
||||
containers, err := cli.ContainerList(context.Background(), container.ListOptions{All: all})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return ctr_list
|
||||
}
|
||||
|
||||
for _, ctr := range containers {
|
||||
if strings.Contains(ctr.Names[0], "ollama") { //&& ctr.Image == "ollama/ollama" {
|
||||
c := Container{ID: ctr.ID, Name: ctr.Names[0], Image: ctr.Image, State: ctr.State, Status: ctr.Status}
|
||||
if ctr.State == "running" {
|
||||
// fmt.Println(ctr.Ports[0])
|
||||
c.Port = int(ctr.Ports[0].PublicPort)
|
||||
}
|
||||
c.IP = host.IP
|
||||
ctr_list.Add(c)
|
||||
// ctr_list = append(ctr_list, c)
|
||||
}
|
||||
}
|
||||
|
||||
// fmt.Println(ctr_list)
|
||||
|
||||
return ctr_list
|
||||
}
|
120
host.go
Normal file
120
host.go
Normal file
|
@ -0,0 +1,120 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Hosts struct {
|
||||
Hosts []Host `json:"hosts"`
|
||||
}
|
||||
|
||||
type Host struct {
|
||||
IP string `json:"ip"`
|
||||
Port string `json:"port"`
|
||||
Containers []Container `json:"containers"`
|
||||
}
|
||||
|
||||
type Model struct {
|
||||
Container string `json:"container"`
|
||||
Name string `json:"name"`
|
||||
Model string `json:"model"`
|
||||
Modified_at string `json:"modified_at"`
|
||||
Size int `json:"size"`
|
||||
Details Details `json:"details"`
|
||||
Ip string `json:"ip"`
|
||||
Port int `json:"port"`
|
||||
State string `json:"state"`
|
||||
}
|
||||
|
||||
type Details struct {
|
||||
Parent_model string `json:"parent_model"`
|
||||
Format string `json:"format"`
|
||||
Family string `json:"family"`
|
||||
Families []string `json:"families"`
|
||||
Parameter_size string `json:"parameter_size"`
|
||||
Quantization_level string `json:"quantization_level"`
|
||||
}
|
||||
|
||||
func get_ollama_tags(hosts Hosts) (Models, error) {
|
||||
|
||||
var ctr Containers
|
||||
|
||||
for _, host := range hosts.Hosts {
|
||||
fmt.Printf("get ollama containers: %s -> %s\n", host.IP, host.Port)
|
||||
ctr.Adds(get_ollama_containers(host, false))
|
||||
}
|
||||
|
||||
retval := []Model{}
|
||||
|
||||
for _, ollama := range ctr.Containers {
|
||||
if ollama.State != "running" {
|
||||
retval = append(retval, Model{Ip: ollama.IP, Port: ollama.Port, State: "stopped"})
|
||||
} else {
|
||||
url := fmt.Sprintf("http://%s:%d/api/tags", ollama.IP, ollama.Port)
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return Models{}, fmt.Errorf("failed to get %s: %v", url, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return Models{}, fmt.Errorf("failed to read body: %v", err)
|
||||
}
|
||||
|
||||
mods := Models{}
|
||||
err = json.Unmarshal(body, &mods)
|
||||
if err != nil {
|
||||
return Models{}, fmt.Errorf("failed to unmarshal JSON: %v", err)
|
||||
}
|
||||
|
||||
for n := range mods.Models {
|
||||
mods.Models[n].Ip = ollama.IP
|
||||
mods.Models[n].Port = ollama.Port
|
||||
mods.Models[n].State = "running"
|
||||
mods.Models[n].Container = ollama.Name
|
||||
fmt.Printf("mod: %s - %s:%d\n", mods.Models[n].Name, mods.Models[n].Ip, mods.Models[n].Port)
|
||||
}
|
||||
|
||||
retval = append(retval, mods.Models...)
|
||||
}
|
||||
}
|
||||
|
||||
return Models{Models: retval}, nil
|
||||
}
|
||||
|
||||
func (h *Hosts) Add(s string) {
|
||||
ip_port := strings.Split(s, ":")
|
||||
h.Hosts = append(h.Hosts, Host{IP: ip_port[0], Port: ip_port[1]})
|
||||
}
|
||||
|
||||
func (h *Hosts) Init(server string) error {
|
||||
|
||||
if debug {
|
||||
fmt.Printf("server: %s\n", server)
|
||||
}
|
||||
|
||||
servers := strings.Split(server, ",")
|
||||
|
||||
if len(servers) == 0 {
|
||||
return fmt.Errorf("no servers specified in config file: '%s'", server)
|
||||
}
|
||||
|
||||
if len(servers) == 1 && servers[0] == "" {
|
||||
return fmt.Errorf("no servers specified in config file: '%s'", server)
|
||||
}
|
||||
|
||||
for _, server := range servers {
|
||||
if !regexp.MustCompile(`^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}$`).MatchString(server) {
|
||||
return fmt.Errorf("invalid server specified: '%s'", server)
|
||||
}
|
||||
h.Add(server)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
10
hosts.cfg
Normal file
10
hosts.cfg
Normal file
|
@ -0,0 +1,10 @@
|
|||
## IP:PORT
|
||||
## IP:PORT
|
||||
## ||
|
||||
## IP:PORT,IP:PORT
|
||||
##
|
||||
#192.168.55.13:2375
|
||||
#192.168.55.15:2375
|
||||
#192.168.55.10:2375
|
||||
192.168.55.10:2375,192.168.55.15:2375
|
||||
192.168.55.13:2375
|
205
main.go
205
main.go
|
@ -1,182 +1,77 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-contrib/cors"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
type Hosts struct {
|
||||
Hosts []Host `json:"hosts"`
|
||||
}
|
||||
|
||||
type Host struct {
|
||||
Name string `json:"name"`
|
||||
IP string `json:"ip"`
|
||||
Port string `json:"port"`
|
||||
Containers []Container `json:"containers"`
|
||||
}
|
||||
|
||||
type Containers struct {
|
||||
Containers []Container `json:"containers"`
|
||||
}
|
||||
|
||||
type Container struct {
|
||||
Name string `json:"names"`
|
||||
Port int `json:"port"`
|
||||
IP string `json:"ip"`
|
||||
Image string `json:"image"`
|
||||
ID string `json:"id"`
|
||||
Status string `json:"status"`
|
||||
State string `json:"state"`
|
||||
}
|
||||
|
||||
type Details struct {
|
||||
Parent_model string `json:"parent_model"`
|
||||
Format string `json:"format"`
|
||||
Family string `json:"family"`
|
||||
Families []string `json:"families"`
|
||||
Parameter_size string `json:"parameter_size"`
|
||||
Quantization_level string `json:"quantization_level"`
|
||||
}
|
||||
|
||||
type Model struct {
|
||||
Container string `json:"container"`
|
||||
Name string `json:"name"`
|
||||
Model string `json:"model"`
|
||||
Modified_at string `json:"modified_at"`
|
||||
Size int `json:"size"`
|
||||
Details Details `json:"details"`
|
||||
Ip string `json:"ip"`
|
||||
Port int `json:"port"`
|
||||
State string `json:"state"`
|
||||
}
|
||||
|
||||
type Models struct {
|
||||
Models []Model `json:"models"`
|
||||
}
|
||||
|
||||
func get_ollama_tags(hosts Hosts) (Models, error) {
|
||||
|
||||
var ctr Containers
|
||||
|
||||
for _, host := range hosts.Hosts {
|
||||
fmt.Printf("HOST: %s -> %s\n", host.Name, host.IP)
|
||||
ctr.Adds(get_ollama_containers(host, false))
|
||||
// ctr = append(ctr, get_ollama_containers(host)...)
|
||||
// fmt.Println(ctr)
|
||||
func read_config() string {
|
||||
f, ferr := os.ReadFile(config)
|
||||
if ferr != nil {
|
||||
log.Fatalf("failed to read config file: %v", ferr)
|
||||
}
|
||||
|
||||
retval := []Model{}
|
||||
tmp_srv := strings.TrimSpace(string(f))
|
||||
tmp_srv = strings.ReplaceAll(tmp_srv, "\r", "")
|
||||
|
||||
for _, ollama := range ctr.Containers {
|
||||
// fmt.Println(ollama)
|
||||
if ollama.State != "running" {
|
||||
retval = append(retval, Model{Ip: ollama.IP, Port: ollama.Port, State: "stopped"})
|
||||
srvs := []string{}
|
||||
/// delete comment rows
|
||||
for _, server := range strings.Split(tmp_srv, "\n") {
|
||||
if !strings.Contains(server, "#") {
|
||||
server = strings.ReplaceAll(server, " ", "")
|
||||
srvs = append(srvs, server)
|
||||
}
|
||||
}
|
||||
|
||||
var server_list string
|
||||
if len(srvs) > 1 {
|
||||
server_list = strings.Join(srvs, ",")
|
||||
} else {
|
||||
url := fmt.Sprintf("http://%s:%d/api/tags", ollama.IP, ollama.Port)
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return Models{}, fmt.Errorf("failed to get %s: %v", url, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return Models{}, fmt.Errorf("failed to read body: %v", err)
|
||||
server_list = srvs[0]
|
||||
}
|
||||
|
||||
mods := Models{}
|
||||
err = json.Unmarshal(body, &mods)
|
||||
if err != nil {
|
||||
return Models{}, fmt.Errorf("failed to unmarshal JSON: %v", err)
|
||||
}
|
||||
fmt.Printf("%+v\n", mods)
|
||||
|
||||
for n := range mods.Models {
|
||||
mods.Models[n].Ip = ollama.IP
|
||||
mods.Models[n].Port = ollama.Port
|
||||
mods.Models[n].State = "running"
|
||||
mods.Models[n].Container = ollama.Name
|
||||
fmt.Printf("mod: %s - %s:%d\n", mods.Models[n].Name, mods.Models[n].Ip, mods.Models[n].Port)
|
||||
if debug {
|
||||
fmt.Printf("config: '%s'\n", server_list)
|
||||
}
|
||||
|
||||
retval = append(retval, mods.Models...)
|
||||
}
|
||||
}
|
||||
|
||||
return Models{Models: retval}, nil
|
||||
}
|
||||
|
||||
func get_ollama_containers(host Host, all bool) Containers {
|
||||
|
||||
ctr_list := Containers{}
|
||||
|
||||
// fmt.Printf("%s -> %s\n", host.Name, host.IP)
|
||||
cli, err := client.NewClientWithOpts(client.WithHost(fmt.Sprintf("tcp://%s:%s", host.IP, host.Port)))
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return ctr_list
|
||||
}
|
||||
defer cli.Close()
|
||||
|
||||
containers, err := cli.ContainerList(context.Background(), container.ListOptions{All: all})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return ctr_list
|
||||
}
|
||||
|
||||
for _, ctr := range containers {
|
||||
if strings.Contains(ctr.Names[0], "ollama") { //&& ctr.Image == "ollama/ollama" {
|
||||
c := Container{ID: ctr.ID, Name: ctr.Names[0], Image: ctr.Image, State: ctr.State, Status: ctr.Status}
|
||||
if ctr.State == "running" {
|
||||
// fmt.Println(ctr.Ports[0])
|
||||
c.Port = int(ctr.Ports[0].PublicPort)
|
||||
}
|
||||
c.IP = host.IP
|
||||
ctr_list.Add(c)
|
||||
// ctr_list = append(ctr_list, c)
|
||||
}
|
||||
}
|
||||
|
||||
// fmt.Println(ctr_list)
|
||||
|
||||
return ctr_list
|
||||
}
|
||||
|
||||
func (h *Hosts) Add(name string, ip string, port string) {
|
||||
h.Hosts = append(h.Hosts, Host{Name: name, IP: ip, Port: port})
|
||||
}
|
||||
|
||||
func (c *Containers) Add(ctr Container) {
|
||||
c.Containers = append(c.Containers, ctr)
|
||||
}
|
||||
|
||||
func (c *Containers) Adds(ctrs Containers) {
|
||||
c.Containers = append(c.Containers, ctrs.Containers...)
|
||||
}
|
||||
|
||||
func (h *Hosts) Init() {
|
||||
h.Add("thor", "192.168.55.13", "2375")
|
||||
h.Add("ironman", "192.168.55.10", "2375")
|
||||
h.Add("hela", "192.168.55.15", "2375")
|
||||
return server_list
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
port := "4000"
|
||||
var server_list string
|
||||
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
|
||||
if version {
|
||||
fmt.Printf("%s: %s\n", os.Args[0], _Version)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if servers == "" && config == "" {
|
||||
fmt.Println("no servers specified")
|
||||
usage()
|
||||
}
|
||||
|
||||
hosts := Hosts{}
|
||||
hosts.Init()
|
||||
if config != "" {
|
||||
server_list = read_config()
|
||||
} else {
|
||||
server_list = servers
|
||||
}
|
||||
|
||||
error := hosts.Init(server_list)
|
||||
|
||||
if error != nil {
|
||||
panic(error)
|
||||
}
|
||||
|
||||
r := gin.Default()
|
||||
r.Use(cors.Default())
|
||||
|
|
38
options.go
Normal file
38
options.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
const (
|
||||
_Version = "0.5.0"
|
||||
)
|
||||
|
||||
var (
|
||||
port string
|
||||
debug bool
|
||||
servers string
|
||||
config string
|
||||
version bool
|
||||
)
|
||||
|
||||
func usage() {
|
||||
fmt.Printf("Usage of %s:\n", path.Base(os.Args[0]))
|
||||
fmt.Printf("\t-p <port>\n")
|
||||
fmt.Printf("\t-D <debug [true|false]>\n")
|
||||
fmt.Printf("\t-s <servers list [ip:port,ip:port...]>\n")
|
||||
fmt.Printf("\t-c <config file>\n")
|
||||
fmt.Println()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&port, "p", "4000", "port")
|
||||
flag.BoolVar(&debug, "D", false, "debug")
|
||||
flag.BoolVar(&debug, "v", false, "debug")
|
||||
flag.StringVar(&servers, "s", "", "servers")
|
||||
flag.StringVar(&config, "c", "", "config file")
|
||||
}
|
Loading…
Add table
Reference in a new issue