Adding basic wrappers
- Wrapper for Host connection called Host - Allows for easier usage of the API - Wrapper for Domains called GuestVM, which pulls VM information and allows other functionality in a better way
This commit is contained in:
parent
bab4f2506b
commit
4ecf05bf82
18
README.md
18
README.md
@ -54,3 +54,21 @@ Overall goals:
|
|||||||
- Connection management (to other libvirt hosts)
|
- Connection management (to other libvirt hosts)
|
||||||
- Create a simple WebUI with HTMX to monitor that stuff
|
- Create a simple WebUI with HTMX to monitor that stuff
|
||||||
- Add the ability to manage that stuff once we can monitor it, through the WebUI.
|
- Add the ability to manage that stuff once we can monitor it, through the WebUI.
|
||||||
|
|
||||||
|
## Special XMLNS definitions
|
||||||
|
|
||||||
|
### Domain
|
||||||
|
|
||||||
|
- `xmlns:clustvirt="https://git.staur.ca/stobbsm/clustvirt"`
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<metadata>
|
||||||
|
<clustvirt:data xmlns:clustvirt="https://git.staur.ca/stobbsm/clustvirt/">
|
||||||
|
<clustvirt:created>true</clustvirt:created>
|
||||||
|
<clustvirt:managed>true</clustvirt:managed>
|
||||||
|
<clustvirt:currentHost>host01</clustvirt:currentHost>
|
||||||
|
<clustvirt:origHost>host02</clustvirt:origHost>
|
||||||
|
<clustvirt:baseGuest>rocky-9-base</clustvirt:baseGuest>
|
||||||
|
</clustvirt:data>
|
||||||
|
</metadata>
|
||||||
|
```
|
||||||
|
53
domains.go
Normal file
53
domains.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"libvirt.org/go/libvirt"
|
||||||
|
)
|
||||||
|
// GuestVM holds a handle is used to communicate to Domains
|
||||||
|
type GuestVM struct {
|
||||||
|
Name string
|
||||||
|
ID uint
|
||||||
|
BackupXML string
|
||||||
|
|
||||||
|
close chan struct{}
|
||||||
|
closeErr chan error
|
||||||
|
dom *libvirt.Domain
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGuest loads guest information by name and returns it
|
||||||
|
func GetGuest(name string, conn *libvirt.Connect) (*GuestVM, error) {
|
||||||
|
g := &GuestVM{
|
||||||
|
Name: name,
|
||||||
|
close: make(chan struct{}),
|
||||||
|
closeErr: make(chan error),
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if g.dom, err = conn.LookupDomainByName(name); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if g.ID, err = g.dom.GetID(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if g.BackupXML, err = g.dom.BackupGetXMLDesc(0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(g.closeErr)
|
||||||
|
<-g.close
|
||||||
|
g.closeErr <- g.dom.Free()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return g, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes an open connection
|
||||||
|
func (g *GuestVM) Close() error {
|
||||||
|
close(g.close)
|
||||||
|
return <-g.closeErr
|
||||||
|
}
|
69
host.go
Normal file
69
host.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"libvirt.org/go/libvirt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Host holds information and acts as a connection handle for a Host
|
||||||
|
// If a connection is closed prematurely, will re-open the connection and
|
||||||
|
// try the attempted method again
|
||||||
|
type Host struct {
|
||||||
|
HostName string
|
||||||
|
|
||||||
|
conn *libvirt.Connect
|
||||||
|
close chan struct{}
|
||||||
|
closeErr chan error
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConnectHost creates a host connection wrapper that can be used regularly
|
||||||
|
func ConnectHost(host string) (*Host, error) {
|
||||||
|
h := &Host{
|
||||||
|
HostName: host,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.connect(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
h.close = make(chan struct{})
|
||||||
|
h.closeErr = make(chan error)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(h.closeErr)
|
||||||
|
<-h.close
|
||||||
|
_, err := h.conn.Close()
|
||||||
|
h.closeErr <- err
|
||||||
|
}()
|
||||||
|
return h, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// connect creates a host connection
|
||||||
|
func (h *Host) connect() error {
|
||||||
|
var err error
|
||||||
|
h.conn, err = libvirt.NewConnect(
|
||||||
|
fmt.Sprintf("qemu+ssh://%s/system", h.HostName),
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGuestByName returns a GuestVM instance that exists on the given host
|
||||||
|
func (h *Host) GetGuestByName(name string) (*GuestVM, error) {
|
||||||
|
if g, err := GetGuest(name, h.conn); err == nil {
|
||||||
|
return g, nil
|
||||||
|
} else {
|
||||||
|
lverr, ok := err.(libvirt.Error)
|
||||||
|
if ok && lverr.Code == libvirt.ERR_INVALID_CONN {
|
||||||
|
// try again after creating a new connection
|
||||||
|
return GetGuest(name, h.conn)
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close triggers closing the host connection
|
||||||
|
func (h *Host) Close() error {
|
||||||
|
close(h.close)
|
||||||
|
return <-h.closeErr
|
||||||
|
}
|
16
main.go
16
main.go
@ -2,23 +2,21 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"libvirt.org/go/libvirt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.Println("Starting clustvirt, the libvirt cluster manager")
|
log.Println("Starting clustvirt, the libvirt cluster manager")
|
||||||
|
|
||||||
// Try connecting to libvirt
|
// Try connecting to libvirt
|
||||||
conn, err := libvirt.NewConnect("qemu+ssh://earth.staur.ca/system")
|
doms, err := GetDomsInCluster("earth.staur.ca", "mars.staur.ca", "venus.staur.ca")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
log.Printf("Domains in cluster: %d", len(doms))
|
||||||
|
// Example of xmlns uri found in libvirt xml definition:
|
||||||
doms, err := conn.ListAllDomains(libvirt.CONNECT_LIST_DOMAINS_ACTIVE | libvirt.CONNECT_LIST_DOMAINS_INACTIVE)
|
// xmlns:libosinfo="http://libosinfo.org/xmlns/libvirt/domain/1.0"
|
||||||
if err != nil {
|
for _, d := range doms {
|
||||||
log.Fatal(err)
|
log.Println(d.GetMetadata(0, "", 0))
|
||||||
|
d.Free()
|
||||||
}
|
}
|
||||||
log.Printf("Domains on earth: %d", len(doms))
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user