name + port allocation.

This commit is contained in:
m1k1o
2021-03-07 22:29:29 +01:00
parent 3eee3276d5
commit 449fa7e3cf
3 changed files with 115 additions and 10 deletions
+19 -8
View File
@@ -15,6 +15,7 @@ import (
"m1k1o/neko_rooms/internal/config"
"m1k1o/neko_rooms/internal/types"
"m1k1o/neko_rooms/internal/utils"
)
const (
@@ -63,17 +64,27 @@ func (manager *RoomManagerCtx) List() ([]types.RoomData, error) {
return result, nil
}
func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (*types.RoomData, error) {
// configs
pathName := "foobar"
eprMin := uint(52135)
eprMax := uint(52145)
// TODO: Check if path name exists.
pathName := settings.Name
if pathName == "" {
var err error
pathName, err = utils.NewUID(32)
if err != nil {
return nil, err
}
}
epr, err := manager.allocatePorts(settings.MaxConnections)
if err != nil {
return nil, err
}
portBindings := nat.PortMap{}
exposedPorts := nat.PortSet{
nat.Port(fmt.Sprintf("%d/udp", frontendPort)): struct{}{},
}
for port := eprMin; port <= eprMax; port++ {
for port := epr.Min; port <= epr.Max; port++ {
portKey := nat.Port(fmt.Sprintf("%d/udp", port))
portBindings[portKey] = []nat.PortBinding{
@@ -91,8 +102,8 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (*types.RoomD
labels := map[string]string{
// Set internal labels
"m1k1o.neko_rooms.canary": labelCanary,
"m1k1o.neko_rooms.epr.min": fmt.Sprintf("%d", eprMin),
"m1k1o.neko_rooms.epr.max": fmt.Sprintf("%d", eprMax),
"m1k1o.neko_rooms.epr.min": fmt.Sprintf("%d", epr.Min),
"m1k1o.neko_rooms.epr.max": fmt.Sprintf("%d", epr.Max),
// Set traefik labels
"traefik.enable": "true",
@@ -121,7 +132,7 @@ func (manager *RoomManagerCtx) Create(settings types.RoomSettings) (*types.RoomD
// List of environment variable to set in the container
Env: append([]string{
fmt.Sprintf("NEKO_BIND=%d", frontendPort),
}, settings.Env(eprMin, eprMax, manager.config.NAT1To1IPs)...),
}, settings.Env(epr.Min, epr.Max, manager.config.NAT1To1IPs)...),
// Name of the image as it was passed by the operator (e.g. could be symbolic)
Image: nekoImage,
// List of labels set to this container
+92
View File
@@ -0,0 +1,92 @@
package room
import (
"fmt"
"sort"
"strconv"
)
type EprPorts struct {
Min uint16
Max uint16
}
func (manager *RoomManagerCtx) allocatePorts(sum uint16) (EprPorts, error) {
min := manager.config.EprMin
max := manager.config.EprMax
epr := EprPorts{
Min: min,
Max: min + sum,
}
ports, err := manager.getUsedPorts()
if err != nil {
return epr, err
}
for _, port := range ports {
if (epr.Min >= port.Min && epr.Min <= port.Max) || (epr.Max >= port.Min && epr.Max <= port.Max) {
epr.Min = port.Max + 1
epr.Max = port.Max + 1 + sum
}
}
if epr.Min > max || epr.Max > max {
return epr, fmt.Errorf("Unable to allocate ports: not enough ports.")
}
return epr, nil
}
func (manager *RoomManagerCtx) getUsedPorts() ([]EprPorts, error) {
containers, err := manager.listContainers()
if err != nil {
return nil, err
}
result := []EprPorts{}
for _, container := range containers {
epr, err := manager.getEprFromLabels(container.Labels)
if err != nil {
return nil, err
}
result = append(result, epr)
}
sort.SliceStable(result, func(i, j int) bool {
return result[i].Min < result[j].Min
})
return result, nil
}
func (manager *RoomManagerCtx) getEprFromLabels(labels map[string]string) (EprPorts, error) {
var err error
epr := EprPorts{}
eprMinStr, ok := labels["m1k1o.neko_rooms.epr.min"]
if !ok {
return epr, fmt.Errorf("Damaged container labels: epr.min not found.")
}
eprMin, err := strconv.ParseUint(eprMinStr, 10, 16)
if err != nil {
return epr, err
}
eprMaxStr, ok := labels["m1k1o.neko_rooms.epr.max"]
if !ok {
return epr, fmt.Errorf("Damaged container labels: epr.max not found.")
}
eprMax, err := strconv.ParseUint(eprMaxStr, 10, 16)
if err != nil {
return epr, err
}
epr.Min = uint16(eprMin)
epr.Max = uint16(eprMax)
return epr, nil
}
+4 -2
View File
@@ -6,7 +6,9 @@ import (
)
type RoomSettings struct {
MaxConnections uint `json:"max_connections"`
Name string `json:"name"`
MaxConnections uint16 `json:"max_connections"`
UserPass string `json:"user_pass"`
AdminPass string `json:"admin_pass"`
@@ -23,7 +25,7 @@ type RoomSettings struct {
AudioPipeline string `json:"audio_pipeline"`
}
func (settings *RoomSettings) Env(eprMin uint, eprMax uint, nat1to1 []string) []string {
func (settings *RoomSettings) Env(eprMin uint16, eprMax uint16, nat1to1 []string) []string {
env := []string{
fmt.Sprintf("NEKO_EPR=%d-%d", eprMin, eprMax),
fmt.Sprintf("NEKO_NAT1TO1=%s", strings.Join(nat1to1, ",")),