-
Notifications
You must be signed in to change notification settings - Fork 213
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial LXD backend discovery support
- Loading branch information
Showing
5 changed files
with
173 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
/** | ||
* lxd.go - LXD API discovery implementation | ||
* | ||
*/ | ||
|
||
package discovery | ||
|
||
import ( | ||
"../config" | ||
"../core" | ||
"../logging" | ||
"../utils" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/lxc/lxd" | ||
) | ||
|
||
const ( | ||
lxdRetryWaitDuration = 2 * time.Second | ||
lxdTimeout = 5 * time.Second | ||
) | ||
|
||
/** | ||
* Create new Discovery with LXD fetch func | ||
*/ | ||
func NewLXDDiscovery(cfg config.DiscoveryConfig) interface{} { | ||
|
||
d := Discovery{ | ||
opts: DiscoveryOpts{lxdRetryWaitDuration}, | ||
fetch: lxdFetch, | ||
cfg: cfg, | ||
} | ||
|
||
return &d | ||
} | ||
|
||
/** | ||
* Fetch backends from LXD API | ||
*/ | ||
func lxdFetch(cfg config.DiscoveryConfig) (*[]core.Backend, error) { | ||
|
||
log := logging.For("lxdFetch") | ||
|
||
log.Info("Fetching unix.socket") | ||
|
||
// Create a simple LXD client that connects to the LXD server over the local | ||
// unix socket. | ||
config := lxd.Config{ | ||
Remotes: map[string]lxd.RemoteConfig{ | ||
"local": lxd.RemoteConfig{ | ||
Addr: "unix:/var/lib/lxd/unix.socket", | ||
}, | ||
}, | ||
} | ||
client, err := lxd.NewClient(&config, "local") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Validate the client config and connectivity | ||
if _, err := client.GetServerConfig(); err != nil { | ||
return nil, err | ||
} | ||
|
||
client.Http.Timeout = utils.ParseDurationOrDefault(cfg.Timeout, lxdTimeout) | ||
|
||
/* Fetch containers */ | ||
containers, err := client.ListContainers() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
/* Create backends from response */ | ||
|
||
backends := []core.Backend{} | ||
|
||
for _, container := range containers { | ||
config := container.Config | ||
if v, ok := config["user.gobetween.label"]; ok { | ||
// label is an arbitrary label to describe the service. | ||
label := v | ||
|
||
// Don't add the backend if the label wasn't requested | ||
// for this service. | ||
if cfg.LXDContainerLabel != "" && label != cfg.LXDContainerLabel { | ||
continue | ||
} | ||
|
||
// private_port is the port on the LXD container. | ||
private_port, ok := config["user.gobetween.private_port"] | ||
if !ok { | ||
msg := fmt.Sprintf("No user.gobetween.private_port set for container %s. Skipping", | ||
container.Name) | ||
log.Warn(msg) | ||
continue | ||
} | ||
|
||
// iface is the container interface to get an IP address. | ||
iface := "eth0" | ||
if v, ok := config["user.gobetween.interface"]; ok { | ||
iface = v | ||
} | ||
|
||
ip, err := lxdDetermineContainerIP(client, container.Name, iface) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var sni string | ||
if v, ok := config["user.gobetween.sni"]; ok { | ||
sni = v | ||
} | ||
|
||
backends = append(backends, core.Backend{ | ||
Target: core.Target{ | ||
Host: ip, | ||
Port: private_port, | ||
}, | ||
Priority: 1, | ||
Weight: 1, | ||
Stats: core.BackendStats{ | ||
Live: true, | ||
}, | ||
Sni: sni, | ||
}) | ||
} | ||
} | ||
|
||
return &backends, nil | ||
} | ||
|
||
func lxdDetermineContainerIP(client *lxd.Client, container string, iface string) (string, error) { | ||
var containerIP string | ||
cstate, err := client.ContainerState(container) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
for i, network := range cstate.Network { | ||
if i == iface { | ||
for _, ip := range network.Addresses { | ||
if ip.Family == "inet" { | ||
containerIP = ip.Address | ||
} | ||
} | ||
} | ||
} | ||
|
||
if containerIP == "" { | ||
return "", fmt.Errorf("Unable to determine IP address for LXD container %s", container) | ||
} | ||
|
||
return containerIP, nil | ||
} |