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
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"flag"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"log"
|
||||||
"net/http"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-contrib/cors"
|
"github.com/gin-contrib/cors"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/container"
|
|
||||||
"github.com/docker/docker/client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Hosts struct {
|
func read_config() string {
|
||||||
Hosts []Host `json:"hosts"`
|
f, ferr := os.ReadFile(config)
|
||||||
}
|
if ferr != nil {
|
||||||
|
log.Fatalf("failed to read config file: %v", ferr)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retval := []Model{}
|
tmp_srv := strings.TrimSpace(string(f))
|
||||||
|
tmp_srv = strings.ReplaceAll(tmp_srv, "\r", "")
|
||||||
|
|
||||||
for _, ollama := range ctr.Containers {
|
srvs := []string{}
|
||||||
// fmt.Println(ollama)
|
/// delete comment rows
|
||||||
if ollama.State != "running" {
|
for _, server := range strings.Split(tmp_srv, "\n") {
|
||||||
retval = append(retval, Model{Ip: ollama.IP, Port: ollama.Port, State: "stopped"})
|
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 {
|
} else {
|
||||||
url := fmt.Sprintf("http://%s:%d/api/tags", ollama.IP, ollama.Port)
|
server_list = srvs[0]
|
||||||
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{}
|
if debug {
|
||||||
err = json.Unmarshal(body, &mods)
|
fmt.Printf("config: '%s'\n", server_list)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = append(retval, mods.Models...)
|
return server_list
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
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 := 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 := gin.Default()
|
||||||
r.Use(cors.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