clustvirt/lib/host/uri.go

152 lines
3.2 KiB
Go
Raw Normal View History

package host
import (
2024-04-21 18:42:59 +00:00
"errors"
"strings"
log "git.staur.ca/stobbsm/simplelog"
)
// URI is a string type, accessed via the pre-defined variables, and represent
// the URI pattern used to connect to a host.
// Example:
// Driver[+Transport]://<host or empty for local>[:PORT]/<path>[?Options&in=uri&format]
type URI struct {
Driver string
Transport string
Path string
Host string
Options []string
}
2024-04-21 18:42:59 +00:00
// Define create and return a custom URI method, following RFC2396,
// keeping in mind that the hostname will be inserted between the transport and path
2024-04-21 18:42:59 +00:00
func Define(driver, transport, path string, options ...string) *URI {
return &URI{
Driver: driver,
Transport: transport,
Path: path,
Options: options,
}
}
2024-04-21 18:42:59 +00:00
var (
URI_QEMU_LOCAL = Define("qemu", "local", "system")
URI_QEMU_SSH = Define("qemu", "ssh", "system")
)
// WithHost sets the hostname as part of a URI. It copies the original URI and returns a new one
func (u *URI) WithHost(host string) *URI {
return &URI{
Driver: u.Driver,
Transport: u.Transport,
Path: u.Path,
Host: host,
Options: u.Options,
}
}
// IsRemote returns true if the URI references a remote trasnport (ssh, tcp or tls)
func (u *URI) IsRemote() bool {
switch u.Transport {
case "ssh":
fallthrough
case "tls":
fallthrough
case "tcp":
return true
default:
return false
}
}
// validTransport makes sure the value of transport if valid or empty. If the transport
// isn't remote, it returns an empty string
2024-04-21 18:42:59 +00:00
func (u *URI) validTransport() bool {
if u.IsRemote() {
2024-04-21 18:42:59 +00:00
return true
}
switch u.Transport {
case "unix":
fallthrough
case "local":
return true
default:
return false
}
}
func (u *URI) validDriver() bool {
switch u.Driver {
case "qemu":
fallthrough
case "xen":
2024-04-21 18:42:59 +00:00
fallthrough
case "lxc":
return true
default:
return false
}
}
// ConnectionString takes a host name to interpolate into a URI and returns the string
func (u *URI) ConnectionString() string {
// Normalize the variables
var driver, transport, path, host string
2024-04-21 18:42:59 +00:00
if !u.validTransport() {
log.Panic("host.URI.ConnectionString").
Err(errors.New("invalid transport")).
Str("transport", u.Transport).
Send()
}
2024-04-21 18:42:59 +00:00
transport = u.Transport
if (u.Host == "localhost" && u.IsRemote()) || u.Host != "localhost" {
host = u.Host
}
// TODO: validate driver, path
2024-04-21 18:42:59 +00:00
if !u.validDriver() {
log.Panic("host.URI.ConnectionString").
Err(errors.New("invalid driver")).
Str("driver", u.Driver).
Send()
}
driver = u.Driver
path = u.Path
var sb strings.Builder
optlen := len(u.Options)
sb.WriteString(driver)
if transport != "" {
sb.WriteRune('+')
sb.WriteString(u.Transport)
}
sb.WriteString("://")
if host != "" {
sb.WriteString(host)
}
sb.WriteRune('/')
sb.WriteString(path)
if optlen > 0 {
sb.WriteRune('?')
for i, o := range u.Options {
sb.WriteString(o)
if optlen != i+1 {
sb.WriteRune('&')
}
}
}
log.Info("Host.ConnectionString").
Str("uri.Driver", u.Driver).
Str("uri.Transport", u.Transport).
Str("uri.Path", u.Path).
Strs("uri.Options", u.Options).
Str("builtUri", sb.String()).Send()
return sb.String()
}
// AddOpt adds more options to the option list
func (u *URI) AddOpt(opt string) {
u.Options = append(u.Options, opt)
}