refactor from all in main to lib
- lib/guest is for managing, displaying, etc. virtual machines - lib/host is the same for hosts
This commit is contained in:
parent
4ecf05bf82
commit
5b16a75bdf
53
domains.go
53
domains.go
@ -1,53 +0,0 @@
|
||||
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
|
||||
}
|
221
lib/guest/domains.go
Normal file
221
lib/guest/domains.go
Normal file
@ -0,0 +1,221 @@
|
||||
// Package guest implements utilities and structured data for libvirt virtual machines
|
||||
package guest
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"libvirt.org/go/libvirt"
|
||||
)
|
||||
|
||||
// Errors
|
||||
|
||||
// ErrVMNotFound error when virtual machine is not found
|
||||
var ErrVMNotFound = errors.New("virtual machine not found")
|
||||
|
||||
// VM holds a handle is used to communicate to Domains
|
||||
type VM struct {
|
||||
Name string
|
||||
HostName string
|
||||
ID uint
|
||||
BackupXML string
|
||||
Autostart bool
|
||||
BlockIOParameters BlockIOParametersInfo
|
||||
Disks []DiskInfo
|
||||
Users []UserInfo
|
||||
OS OSInfo
|
||||
TimeZone TimeZoneInfo
|
||||
NetIFace []NetIFaceInfo
|
||||
|
||||
close chan struct{}
|
||||
closeErr chan error
|
||||
dom *libvirt.Domain
|
||||
}
|
||||
|
||||
// BlockIOParametersInfo is the struct describing VM block IO parameters
|
||||
type BlockIOParametersInfo struct {
|
||||
Weight uint
|
||||
DeviceWeight string
|
||||
DeviceReadIops string
|
||||
DeviceWriteIops string
|
||||
DeviceReadBps string
|
||||
DeviceWriteBps string
|
||||
}
|
||||
|
||||
// DiskInfo is the struct for guest disk information, and is used in VM
|
||||
type DiskInfo struct {
|
||||
Name string
|
||||
Partition bool
|
||||
Alias string
|
||||
GuestAlias string
|
||||
DiskDependency []string
|
||||
}
|
||||
|
||||
// UserInfo is the struct for VM user information, and is used in VM
|
||||
type UserInfo struct {
|
||||
Name string
|
||||
Domain string
|
||||
LoginTime time.Time
|
||||
}
|
||||
|
||||
// OSInfo is the struct for guest operating system information, and is used in VM
|
||||
type OSInfo struct {
|
||||
ID string
|
||||
Name string
|
||||
PrettyName string
|
||||
Version string
|
||||
VersionID string
|
||||
KernelRelease string
|
||||
KernelVersion string
|
||||
Machine string
|
||||
Variant string
|
||||
VariantID string
|
||||
}
|
||||
|
||||
// TimeZoneInfo provides guest timezone information, and is used in VM
|
||||
type TimeZoneInfo struct {
|
||||
Name string
|
||||
Offset int
|
||||
}
|
||||
|
||||
// NetIFaceInfo provides guest Network Interface information, and is used in VM
|
||||
type NetIFaceInfo struct {
|
||||
Name string
|
||||
HWAddr string
|
||||
IP []IPInfo
|
||||
}
|
||||
|
||||
// IPInfo provides guest IP network information, and is used in NetIFaceInfo
|
||||
type IPInfo struct {
|
||||
Type string
|
||||
Addr string
|
||||
Prefix uint
|
||||
}
|
||||
|
||||
// GetGuest loads guest information by name and returns it
|
||||
func GetGuest(name string, conn *libvirt.Connect) (*VM, error) {
|
||||
g := &VM{
|
||||
Name: name,
|
||||
close: make(chan struct{}),
|
||||
closeErr: make(chan error),
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
// If the domain can't be found by name, exit early with an error
|
||||
if g.dom, err = conn.LookupDomainByName(name); err != nil {
|
||||
return g, ErrVMNotFound
|
||||
}
|
||||
if g.ID, err = g.dom.GetID(); err != nil {
|
||||
return g, err
|
||||
}
|
||||
if g.BackupXML, err = g.dom.BackupGetXMLDesc(0); err != nil {
|
||||
return g, err
|
||||
}
|
||||
if g.Autostart, err = g.dom.GetAutostart(); err != nil {
|
||||
return g, err
|
||||
}
|
||||
|
||||
blkiop, err := g.dom.GetBlkioParameters(0)
|
||||
if err != nil {
|
||||
return g, err
|
||||
}
|
||||
g.BlockIOParameters.Weight = blkiop.Weight
|
||||
g.BlockIOParameters.DeviceWeight = setNotSet(blkiop.DeviceWeight, blkiop.DeviceWeightSet)
|
||||
g.BlockIOParameters.DeviceReadIops = setNotSet(blkiop.DeviceReadIops, blkiop.DeviceReadIopsSet)
|
||||
g.BlockIOParameters.DeviceWriteIops = setNotSet(blkiop.DeviceWriteIops, blkiop.DeviceWriteIopsSet)
|
||||
g.BlockIOParameters.DeviceReadBps = setNotSet(blkiop.DeviceReadBps, blkiop.DeviceReadBpsSet)
|
||||
g.BlockIOParameters.DeviceWriteBps = setNotSet(blkiop.DeviceWriteBps, blkiop.DeviceWriteBpsSet)
|
||||
|
||||
// Set as much guest info as possible
|
||||
info, err := g.dom.GetGuestInfo(
|
||||
libvirt.DOMAIN_GUEST_INFO_USERS|libvirt.DOMAIN_GUEST_INFO_OS|
|
||||
libvirt.DOMAIN_GUEST_INFO_DISKS|libvirt.DOMAIN_GUEST_INFO_HOSTNAME|
|
||||
libvirt.DOMAIN_GUEST_INFO_INTERFACES|libvirt.DOMAIN_GUEST_INFO_TIMEZONE|
|
||||
libvirt.DOMAIN_GUEST_INFO_FILESYSTEM,
|
||||
0,
|
||||
)
|
||||
if err != nil {
|
||||
return g, err
|
||||
}
|
||||
// Set disk info
|
||||
if len(info.Disks) > 0 {
|
||||
g.Disks = make([]DiskInfo, len(info.Disks))
|
||||
for i, n := range info.Disks {
|
||||
g.Disks[i].Name = setNotSet(n.Name, n.NameSet)
|
||||
g.Disks[i].Alias = setNotSet(n.Alias, n.AliasSet)
|
||||
g.Disks[i].Partition = n.Partition
|
||||
g.Disks[i].GuestAlias = setNotSet(n.GuestAlias, n.GuestAliasSet)
|
||||
g.Disks[i].DiskDependency = make([]string, len(n.Dependencies))
|
||||
for j, k := range n.Dependencies {
|
||||
g.Disks[i].DiskDependency[j] = setNotSet(k.Name, k.NameSet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(info.Users) > 0 {
|
||||
g.Users = make([]UserInfo, len(info.Users))
|
||||
for i, n := range info.Users {
|
||||
g.Users[i].Name = setNotSet(n.Name, n.NameSet)
|
||||
g.Users[i].Domain = setNotSet(n.Domain, n.DomainSet)
|
||||
g.Users[i].LoginTime = time.Unix(int64(n.LoginTime), 0)
|
||||
}
|
||||
}
|
||||
|
||||
g.OS.ID = setNotSet(info.OS.ID, info.OS.IDSet)
|
||||
g.OS.Name = setNotSet(info.OS.Name, info.OS.NameSet)
|
||||
g.OS.Machine = setNotSet(info.OS.Machine, info.OS.MachineSet)
|
||||
g.OS.Variant = setNotSet(info.OS.Variant, info.OS.VariantSet)
|
||||
g.OS.Version = setNotSet(info.OS.Version, info.OS.VersionSet)
|
||||
g.OS.VariantID = setNotSet(info.OS.VariantID, info.OS.VariantIDSet)
|
||||
g.OS.VersionID = setNotSet(info.OS.VersionID, info.OS.VersionIDSet)
|
||||
g.OS.PrettyName = setNotSet(info.OS.PrettyName, info.OS.PrettyNameSet)
|
||||
g.OS.KernelRelease = setNotSet(info.OS.KernelRelease, info.OS.KernelReleaseSet)
|
||||
g.OS.KernelVersion = setNotSet(info.OS.KernelVersion, info.OS.KernelVersionSet)
|
||||
g.TimeZone.Name = setNotSet(info.TimeZone.Name, info.TimeZone.NameSet)
|
||||
g.TimeZone.Offset = info.TimeZone.Offset
|
||||
|
||||
// Set the hostname from the guest if it is set, otherwise use the VM name
|
||||
if info.HostnameSet {
|
||||
g.HostName = info.Hostname
|
||||
} else {
|
||||
g.HostName = g.Name
|
||||
}
|
||||
if len(info.Interfaces) > 0 {
|
||||
g.NetIFace = make([]NetIFaceInfo, len(info.Interfaces))
|
||||
for i, n := range info.Interfaces {
|
||||
g.NetIFace[i].HWAddr = setNotSet(n.Hwaddr, n.HwaddrSet)
|
||||
g.NetIFace[i].Name = setNotSet(n.Name, n.NameSet)
|
||||
if len(n.Addrs) > 0 {
|
||||
g.NetIFace[i].IP = make([]IPInfo, len(n.Addrs))
|
||||
for j, a := range n.Addrs {
|
||||
g.NetIFace[i].IP[j].Addr = setNotSet(a.Addr, a.AddrSet)
|
||||
g.NetIFace[i].IP[j].Type = setNotSet(a.Type, a.TypeSet)
|
||||
g.NetIFace[i].IP[j].Prefix = a.Prefix
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer close(g.closeErr)
|
||||
<-g.close
|
||||
g.closeErr <- g.dom.Free()
|
||||
}()
|
||||
|
||||
return g, nil
|
||||
}
|
||||
|
||||
// helper function to set a string value to "NotSet" if it wasn't actually set
|
||||
func setNotSet(v string, s bool) string {
|
||||
if s {
|
||||
return v
|
||||
}
|
||||
return "Notset"
|
||||
}
|
||||
|
||||
// Close closes an open connection
|
||||
func (g *VM) Close() error {
|
||||
close(g.close)
|
||||
return <-g.closeErr
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
package main
|
||||
package host
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/lib/guest"
|
||||
"libvirt.org/go/libvirt"
|
||||
)
|
||||
|
||||
@ -49,17 +50,18 @@ func (h *Host) connect() error {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
func (h *Host) GetGuestByName(name string) (*guest.VM, error) {
|
||||
g, err := guest.GetGuest(name, h.conn)
|
||||
if 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 guest.GetGuest(name, h.conn)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Close triggers closing the host connection
|
Loading…
Reference in New Issue
Block a user