mirror of
https://github.com/ScottESanDiego/virtwold.git
synced 2024-12-22 13:45:33 +00:00
Switch to libvirt-go and libvirt-go-xml
This commit is contained in:
parent
74c4ca5fa1
commit
7f1162052a
2
go.mod
2
go.mod
@ -14,4 +14,6 @@ require (
|
|||||||
golang.org/x/net v0.5.0 // indirect
|
golang.org/x/net v0.5.0 // indirect
|
||||||
golang.org/x/sys v0.4.0 // indirect
|
golang.org/x/sys v0.4.0 // indirect
|
||||||
golang.org/x/text v0.6.0 // indirect
|
golang.org/x/text v0.6.0 // indirect
|
||||||
|
libvirt.org/go/libvirt v1.9008.0 // indirect
|
||||||
|
libvirt.org/go/libvirtxml v1.9008.0 // indirect
|
||||||
)
|
)
|
||||||
|
4
go.sum
4
go.sum
@ -61,3 +61,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
libvirt.org/go/libvirt v1.9008.0 h1:LLpjuSQm9gChnx7I/44SLLg/eyvTnJpcMAFmKot65Zc=
|
||||||
|
libvirt.org/go/libvirt v1.9008.0/go.mod h1:1WiFE8EjZfq+FCVog+rvr1yatKbKZ9FaFMZgEqxEJqQ=
|
||||||
|
libvirt.org/go/libvirtxml v1.9008.0 h1:xo2U9SqUsufTFtbyjiqs6oDdF329cvtRdqttWN7eojk=
|
||||||
|
libvirt.org/go/libvirtxml v1.9008.0/go.mod h1:7Oq2BLDstLr/XtoQD8Fr3mfDNrzlI3utYKySXF2xkng=
|
||||||
|
95
virtwold.go
95
virtwold.go
@ -15,15 +15,11 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/antchfx/xmlquery"
|
|
||||||
"github.com/digitalocean/go-libvirt"
|
|
||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/pcap"
|
"github.com/google/gopacket/pcap"
|
||||||
|
"libvirt.org/go/libvirt"
|
||||||
|
"libvirt.org/go/libvirtxml"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -75,75 +71,70 @@ func GrabMACAddr(packet gopacket.Packet) (string, error) {
|
|||||||
|
|
||||||
func WakeVirtualMachine(mac string) bool {
|
func WakeVirtualMachine(mac string) bool {
|
||||||
// Connect to the local libvirt socket
|
// Connect to the local libvirt socket
|
||||||
c, err := net.DialTimeout("unix", "/var/run/libvirt/libvirt-sock", 2*time.Second)
|
connection, err := libvirt.NewConnect("qemu+tcp:///system")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to dial libvirt: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
l := libvirt.New(c)
|
|
||||||
if err := l.Connect(); err != nil {
|
|
||||||
log.Fatalf("failed to connect: %v", err)
|
log.Fatalf("failed to connect: %v", err)
|
||||||
}
|
}
|
||||||
|
defer connection.Close()
|
||||||
|
|
||||||
// Get a list of all VMs (aka Domains) configured so we can loop through them
|
// Get a list of all inactive VMs (aka Domains) configured so we can loop through them
|
||||||
flags := libvirt.ConnectListDomainsActive | libvirt.ConnectListDomainsInactive
|
domains, err := connection.ListAllDomains(libvirt.CONNECT_LIST_DOMAINS_INACTIVE)
|
||||||
domains, _, err := l.ConnectListAllDomains(1, flags)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to retrieve domains: %v", err)
|
log.Fatalf("failed to retrieve domains: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, d := range domains {
|
for _, domain := range domains {
|
||||||
//fmt.Printf("%d\t%s\t%x\n", d.ID, d.Name, d.UUID)
|
|
||||||
|
|
||||||
// Now we get the XML Description for each domain
|
// Now we get the XML Description for each domain
|
||||||
xmldesc, err := l.DomainGetXMLDesc(d, 0)
|
xmldesc, err := domain.GetXMLDesc(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed retrieving interfaces: %v", err)
|
log.Fatalf("failed retrieving XML: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Feed the XML output into xmlquery
|
// Get the details for each domain
|
||||||
querydoc, err := xmlquery.Parse(strings.NewReader(xmldesc))
|
domcfg := &libvirtxml.Domain{}
|
||||||
|
err = domcfg.Unmarshal(xmldesc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to parse XML: %v", err)
|
log.Fatalf("failed retrieving domain configuration: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform an xmlquery to look for the MAC address in the XML
|
// Loop through each interface found
|
||||||
for _, list := range xmlquery.Find(querydoc, "//domain/devices/interface/mac/@address") {
|
for _, iface := range domcfg.Devices.Interfaces {
|
||||||
// Use the strings.EqualFold function to do a case-insensitive comparison of MACs
|
domainmac := iface.MAC.Address
|
||||||
if strings.EqualFold(list.InnerText(), mac) {
|
|
||||||
stateInt, _, err := l.DomainGetState(d, 0)
|
if domainmac == mac {
|
||||||
|
// We'll use the name later, so may as well get it here
|
||||||
|
name := domcfg.Name
|
||||||
|
|
||||||
|
// Get the state of the VM and take action
|
||||||
|
state, _, err := domain.GetState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to check domain state: %v", err)
|
log.Fatalf("failed to check domain state: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
state := libvirt.DomainState(stateInt)
|
|
||||||
// fmt.Printf("Domain state is %v\n", state)
|
|
||||||
|
|
||||||
switch state {
|
switch state {
|
||||||
case libvirt.DomainShutoff, libvirt.DomainCrashed:
|
case libvirt.DOMAIN_SHUTDOWN, libvirt.DOMAIN_SHUTOFF, libvirt.DOMAIN_CRASHED:
|
||||||
fmt.Printf("Waking system: %s at MAC %s\n", d.Name, mac)
|
fmt.Printf("Waking system: %s at MAC %s\n", name, mac)
|
||||||
if err := l.DomainCreate(d); err != nil {
|
if err := domain.Create(); err != nil {
|
||||||
log.Fatalf("Failed to start domain: %v", err)
|
log.Fatalf("Failed to start domain: %v", err)
|
||||||
}
|
}
|
||||||
case libvirt.DomainPmsuspended:
|
|
||||||
fmt.Printf("PM Wakeup system: %s at MAC %s\n", d.Name, mac)
|
case libvirt.DOMAIN_PMSUSPENDED:
|
||||||
if err := l.DomainPmWakeup(d, 0); err != nil {
|
fmt.Printf("Unsuspending system: %s at MAC %s\n", name, mac)
|
||||||
log.Fatalf("Failed to pm wakeup domain: %v", err)
|
if err := domain.Create(); err != nil {
|
||||||
}
|
log.Fatalf("Failed to unsuspend domain: %v", err)
|
||||||
case libvirt.DomainPaused:
|
|
||||||
fmt.Printf("Resume system: %s at MAC %s\n", d.Name, mac)
|
|
||||||
if err := l.DomainResume(d); err != nil {
|
|
||||||
log.Fatalf("Failed to resume domain: %v", err)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
fmt.Printf("System %s is already running or in a state that cannot be woken from. State: %d\n", d.Name, state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := l.Disconnect(); err != nil {
|
case libvirt.DOMAIN_PAUSED:
|
||||||
log.Fatalf("failed to disconnect: %v", err)
|
fmt.Printf("Resuming system: %s at MAC %s\n", name, mac)
|
||||||
|
if err := domain.Create(); err != nil {
|
||||||
|
log.Fatalf("Failed to resume domain: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
fmt.Printf("System is already running or in a state that cannot be woken from. State: %d\n", state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
Loading…
Reference in New Issue
Block a user