adding more libvirtxml migrations

This commit is contained in:
Matthew Stobbs 2024-03-20 11:36:53 -06:00
parent de93204e3d
commit 3862e3d4e9
3 changed files with 132 additions and 158 deletions

4
go.mod
View File

@ -5,8 +5,9 @@ go 1.22.1
require ( require (
github.com/a-h/templ v0.2.598 github.com/a-h/templ v0.2.598
github.com/go-chi/chi/v5 v5.0.12 github.com/go-chi/chi/v5 v5.0.12
github.com/jaypipes/pcidb v1.0.0
github.com/wcharczuk/go-chart/v2 v2.1.1 github.com/wcharczuk/go-chart/v2 v2.1.1
gopkg.in/ffmt.v1 v1.5.6 golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81
libvirt.org/go/libvirt v1.10001.0 libvirt.org/go/libvirt v1.10001.0
libvirt.org/go/libvirtxml v1.10001.0 libvirt.org/go/libvirtxml v1.10001.0
) )
@ -14,7 +15,6 @@ require (
require ( require (
github.com/blend/go-sdk v1.20220411.3 // indirect github.com/blend/go-sdk v1.20220411.3 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/jaypipes/pcidb v1.0.0 // indirect
github.com/mitchellh/go-homedir v1.0.0 // indirect github.com/mitchellh/go-homedir v1.0.0 // indirect
golang.org/x/image v0.11.0 // indirect golang.org/x/image v0.11.0 // indirect
) )

4
go.sum
View File

@ -17,6 +17,8 @@ github.com/wcharczuk/go-chart/v2 v2.1.1/go.mod h1:CyCAUt2oqvfhCl6Q5ZvAZwItgpQKZO
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81 h1:6R2FC06FonbXQ8pK11/PDFY6N6LWlf9KlzibaCapmqc=
golang.org/x/exp v0.0.0-20240318143956-a85f2c67cd81/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo= golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo=
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8= golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@ -47,8 +49,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/ffmt.v1 v1.5.6 h1:4Bu3riZp5sAIXW2T/18JM9BkwJLodurXFR0f7PXp+cw=
gopkg.in/ffmt.v1 v1.5.6/go.mod h1:LssvGOZFiBGoBcobkTqnyh+uN1VzIRoibW+c0JI/Ha4=
libvirt.org/go/libvirt v1.10001.0 h1:lEVDNE7xfzmZXiDEGIS8NvJSuaz11OjRXw+ufbQEtPY= libvirt.org/go/libvirt v1.10001.0 h1:lEVDNE7xfzmZXiDEGIS8NvJSuaz11OjRXw+ufbQEtPY=
libvirt.org/go/libvirt v1.10001.0/go.mod h1:1WiFE8EjZfq+FCVog+rvr1yatKbKZ9FaFMZgEqxEJqQ= libvirt.org/go/libvirt v1.10001.0/go.mod h1:1WiFE8EjZfq+FCVog+rvr1yatKbKZ9FaFMZgEqxEJqQ=
libvirt.org/go/libvirtxml v1.10001.0 h1:r9WBs24r3mxIG3/hAMRRwDMy4ZaPHmhHjw72o/ceXic= libvirt.org/go/libvirtxml v1.10001.0 h1:r9WBs24r3mxIG3/hAMRRwDMy4ZaPHmhHjw72o/ceXic=

View File

@ -11,9 +11,6 @@ import (
"sync" "sync"
"git.staur.ca/stobbsm/clustvirt/lib/guest" "git.staur.ca/stobbsm/clustvirt/lib/guest"
"git.staur.ca/stobbsm/clustvirt/lib/secret"
"git.staur.ca/stobbsm/clustvirt/lib/storagepool"
"git.staur.ca/stobbsm/clustvirt/lib/storagevol"
"libvirt.org/go/libvirt" "libvirt.org/go/libvirt"
"libvirt.org/go/libvirtxml" "libvirt.org/go/libvirtxml"
) )
@ -37,23 +34,23 @@ type Host struct {
// Secure indicates if the connection is secure // Secure indicates if the connection is secure
Secure bool Secure bool
// HostInfo provides basic HW information about a host // HostInfo provides basic HW information about a host
HostInfo libvirtxml.CapsHost HostInfo *libvirtxml.CapsHost
// NodeMemory provides basic memory information about the Host // NodeMemory provides basic memory information about the Host
NodeMemory NodeMemoryInfo NodeMemory *NodeMemoryInfo
// VMList is the list of virtual machines available to the host // VMList is the list of virtual machines available to the host
VMList []libvirtxml.Domain VMList []*libvirtxml.Domain
// NetIfList is the list of network interfaces on the host // NetIfList is the list of network interfaces on the host
NetIfFList []libvirtxml.Interface NetIfFList []*libvirtxml.Interface
// NetworkList is the list of defined networks on the host // NetworkList is the list of defined networks on the host
NetworkList []libvirtxml.Network NetworkList []*libvirtxml.Network
// DeviceList is the list of devices on the host // DeviceList is the list of devices on the host
DeviceList []libvirtxml.NodeDevice DeviceList []*libvirtxml.NodeDevice
// SecretList provides a list of secrets available to the host // SecretList provides a list of secrets available to the host
SecretList []libvirtxml.Secret SecretList []*libvirtxml.Secret
// StoragePoolList provides the list of stoarge ppols available to the host // StoragePoolList provides the list of stoarge ppols available to the host
StoragePoolList []libvirtxml.StoragePool StoragePoolList []*libvirtxml.StoragePool
// VolumeList is the list of volumes available on the host // VolumeList is the list of volumes available on the host
VolumeList []libvirtxml.StorageVolume VolumeList []*libvirtxml.StorageVolume
uri *URI uri *URI
conn *libvirt.Connect conn *libvirt.Connect
@ -128,13 +125,14 @@ func (h *Host) getInfo() {
wg := new(sync.WaitGroup) wg := new(sync.WaitGroup)
infoFuncs := []func(){ infoFuncs := []func(){
h.getDevicesInfo, h.hostInfo,
// h.getDomainInfo, h.memoryInfo,
h.getIfaceInfo, h.getStoragePools,
h.getNetsInfo, h.getNetsInfo,
h.getNodeInfo, h.getIfaceInfo,
// h.getSecretsInfo, h.getDevicesInfo,
// h.getStoragePools, h.getDomainInfo,
h.getSecretsInfo,
} }
for _, f := range infoFuncs { for _, f := range infoFuncs {
@ -148,159 +146,40 @@ func (h *Host) getInfo() {
wg.Wait() wg.Wait()
} }
func (h *Host) getStoragePools() { func (h *Host) hostInfo() {
spools, err := h.conn.ListAllStoragePools(0)
if err != nil {
log.Println(err)
}
if len(spools) > 0 {
h.StoragePoolList = make([]StoragePoolInfo, len(spools))
for i, s := range spools {
if h.StoragePoolList[i].XML, err = s.GetXMLDesc(0); err != nil {
log.Println(err)
}
if h.StoragePoolList[i].Name, err = s.GetName(); err != nil {
log.Println(err)
}
if h.StoragePoolList[i].UUID, err = s.GetUUID(); err != nil {
log.Println(err)
}
if h.StoragePoolList[i].Active, err = s.IsActive(); err != nil {
log.Println(err)
}
if h.StoragePoolList[i].Persistent, err = s.IsPersistent(); err != nil {
log.Println(err)
}
if h.StoragePoolList[i].AutoStart, err = s.GetAutostart(); err != nil {
log.Println(err)
}
spInfo, err := s.GetInfo()
if err != nil {
log.Println(err)
}
h.StoragePoolList[i].State = storagepool.StoragePoolStateMap[spInfo.State]
h.StoragePoolList[i].Capacity = spInfo.Capacity
h.StoragePoolList[i].Allocation = spInfo.Allocation
h.StoragePoolList[i].Available = spInfo.Available
spoolXML := &libvirtxml.StoragePool{}
if err = spoolXML.Unmarshal(h.StoragePoolList[i].XML); err != nil {
log.Println(err)
}
h.StoragePoolList[i].Type = spoolXML.Type
for _, t := range storagepool.NetTypes {
if h.StoragePoolList[i].Type == t {
h.StoragePoolList[i].IsNet = true
h.StoragePoolList[i].HAEnabled = true
continue
}
}
svols, err := s.ListAllStorageVolumes(0)
if err != nil {
log.Println(err)
}
if len(svols) > 0 {
h.StoragePoolList[i].Volumes = make([]VolumeInfo, len(svols))
for j, sv := range svols {
if h.StoragePoolList[i].Volumes[j].Name, err = sv.GetName(); err != nil {
log.Println(err)
}
if h.StoragePoolList[i].Volumes[j].Key, err = sv.GetKey(); err != nil {
log.Println(err)
}
if h.StoragePoolList[i].Volumes[j].Path, err = sv.GetPath(); err != nil {
log.Println(err)
}
svInfo, err := sv.GetInfo() // Type, Capacity, Allocation
if err != nil {
log.Println(err)
}
h.StoragePoolList[i].Volumes[j].Type = storagevol.StorageVolTypeMap[svInfo.Type]
h.StoragePoolList[i].Volumes[j].Capacity = svInfo.Capacity
h.StoragePoolList[i].Volumes[j].Allocation = svInfo.Allocation
if h.StoragePoolList[i].Volumes[j].XML, err = sv.GetXMLDesc(0); err != nil {
log.Println(err)
}
sv.Free()
}
}
s.Free()
}
}
}
func (h *Host) getSecretsInfo() {
nsecrets, err := h.conn.ListAllSecrets(0)
if err != nil {
log.Println(err)
}
if len(nsecrets) > 0 {
h.SecretList = make([]SecretInfo, len(nsecrets))
for i, s := range nsecrets {
if h.SecretList[i].XML, err = s.GetXMLDesc(0); err != nil {
log.Println(err)
}
stype, err := s.GetUsageType()
if err != nil {
log.Println(err)
}
h.SecretList[i].Type = secret.SecretUsageTypeMap[stype]
s.Free()
}
}
}
func (h *Host) getNodeInfo() {
var err error var err error
h.AvailableCPUTypes, err = h.conn.GetCPUModelNames("x86_64", 0)
if err != nil {
log.Println("Error getting cpu model names", err)
}
ni, err := h.conn.GetNodeInfo() rawxml, err := h.conn.GetCapabilities()
if err != nil { if err != nil {
log.Println(err) log.Printf("error getting host capabilities XML: %s", err)
} }
h.HostInfo.Model = ni.Model xmldoc := &libvirtxml.Caps{}
h.HostInfo.Memory = ni.Memory if err = xmldoc.Unmarshal(rawxml); err != nil {
h.HostInfo.Cpus = ni.Cpus log.Printf("error parsing host capabilities XML: %s", err)
h.HostInfo.MHz = ni.MHz }
h.HostInfo.Nodes = ni.Nodes h.HostInfo = &xmldoc.Host
h.HostInfo.Sockets = ni.Sockets
h.HostInfo.Cores = ni.Cores
h.HostInfo.Threads = ni.Threads
h.SystemHostName, err = h.conn.GetHostname() h.SystemHostName, err = h.conn.GetHostname()
if err != nil { if err != nil {
log.Println(err) log.Println("error getting system host name: %s", err)
} } else {
if h.SystemHostName == "" {
h.SystemHostName = h.HostName h.SystemHostName = h.HostName
} }
h.LibVersion, err = h.conn.GetLibVersion() h.LibVersion, err = h.conn.GetLibVersion()
if err != nil { if err != nil {
log.Println(err) log.Println(err)
} }
h.FreeMemory, err = h.conn.GetFreeMemory() }
if err != nil {
log.Println(err)
}
func (h *Host) memoryInfo() {
mi, err := h.conn.GetMemoryStats(libvirt.NODE_MEMORY_STATS_ALL_CELLS, 0) mi, err := h.conn.GetMemoryStats(libvirt.NODE_MEMORY_STATS_ALL_CELLS, 0)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
} }
h.NodeMemory.Total = mi.Total h.NodeMemory = &NodeMemoryInfo{
h.NodeMemory.Free = mi.Free Total: mi.Total,
h.NodeMemory.Buffers = mi.Buffers Free: mi.Free,
h.NodeMemory.Cached = mi.Cached Buffers: mi.Buffers,
Cached: mi.Cached,
h.StorageCapabilities, err = h.conn.GetStoragePoolCapabilities(0)
if err != nil {
log.Println(err)
} }
h.SysInfo, err = h.conn.GetSysinfo(0) h.SysInfo, err = h.conn.GetSysinfo(0)
@ -322,6 +201,101 @@ func (h *Host) getNodeInfo() {
} }
} }
func (h *Host) getStoragePools() {
// Get list of all storage pools on the host
spools, err := h.conn.ListAllStoragePools(0)
if err != nil {
log.Println(err)
}
if len(spools) > 0 {
h.StoragePoolList = make([]*libvirtxml.StoragePool, len(spools))
for i, s := range spools {
// run in a function to allow defer s.Free()
func() {
defer s.Free()
// Get the XML represenation of each storage pool, parse it with libvirtxml
rawxml, err := s.GetXMLDesc(0)
if err != nil {
log.Println("error getting storage pool xml: %s", err)
return
}
xmldoc := &libvirtxml.StoragePool{}
err = xmldoc.Unmarshal(rawxml)
if err != nil {
log.Println("error parsing storage pool XML: %s", err)
return
}
h.StoragePoolList[i] = xmldoc
// Get list of all storage volumes in the current storage pool
svols, err := s.ListAllStorageVolumes(0)
if err != nil {
log.Println(err)
}
if len(svols) > 0 {
// define temporary variable to hold slice of StorageVolume, that can
// either be appended to the existing slice, or used in place of the newly
// defined slice
tvl := make([]*libvirtxml.StorageVolume, len(svols))
for j, sv := range svols {
// run in a function so I can defer the sv.Free() call
func() {
defer sv.Free()
rawxml, err = sv.GetXMLDesc(0)
if err != nil {
log.Printf("error getting XML from storage volume: %s", err)
return
}
xmldoc := &libvirtxml.StorageVolume{}
err = xmldoc.Unmarshal(rawxml)
if err != nil {
log.Printf("error parsing storage volume XML: %s", err)
return
}
tvl[j] = xmldoc
}()
}
// Append the contents of tvl to h.VolumeList
if h.VolumeList == nil {
h.VolumeList = []*libvirtxml.StorageVolume{}
}
// Only append if the temporary storage volume isn't nil
for _, tsv := range tvl {
if tsv != nil {
h.VolumeList = append(h.VolumeList, tsv)
}
}
}
}()
}
}
}
func (h *Host) getSecretsInfo() {
nsecrets, err := h.conn.ListAllSecrets(0)
if err != nil {
log.Printf("error loading secrets from host: %s", err)
}
if len(nsecrets) > 0 {
h.SecretList = make([]*libvirtxml.Secret, len(nsecrets))
for i, s := range nsecrets {
func() {
defer s.Free()
rawxml, err := s.GetXMLDesc(0)
if err != nil {
log.Printf("error getting secret XML", err)
}
xmldoc := &libvirtxml.Secret{}
if err = xmldoc.Unmarshal(rawxml); err != nil {
log.Printf("error parsing secret XML: %s", err)
}
h.SecretList[i] = xmldoc
}()
}
}
}
func (h *Host) getDomainInfo() { func (h *Host) getDomainInfo() {
// getDomainInfo // getDomainInfo
doms, err := h.conn.ListAllDomains(0) doms, err := h.conn.ListAllDomains(0)