lint cleanups

This commit is contained in:
Duncan Mac-Vicar P 2023-01-02 01:33:31 +01:00
parent 4a99136330
commit 01e507d95b
33 changed files with 330 additions and 480 deletions

View File

@ -99,19 +99,19 @@ func (ci *defCloudInit) UploadIso(client *Client, iso string) (string, error) {
volumeDefXML, err := xml.Marshal(volumeDef)
if err != nil {
return "", fmt.Errorf("error serializing libvirt volume: %s", err)
return "", fmt.Errorf("error serializing libvirt volume: %w", err)
}
// create the volume
volume, err := virConn.StorageVolCreateXML(pool, string(volumeDefXML), 0)
if err != nil {
return "", fmt.Errorf("error creating libvirt volume for cloudinit device %s: %s", ci.Name, err)
return "", fmt.Errorf("error creating libvirt volume for cloudinit device %s: %w", ci.Name, err)
}
// upload ISO file
err = img.Import(newCopier(virConn, &volume, uint64(size)), volumeDef)
if err != nil {
return "", fmt.Errorf("error while uploading cloudinit %s: %s", img.String(), err)
return "", fmt.Errorf("error while uploading cloudinit %s: %w", img.String(), err)
}
if volume.Key == "" {
@ -160,7 +160,7 @@ func (ci *defCloudInit) createISO() (string, error) {
log.Printf("About to execute cmd: %+v", cmd)
if err = cmd.Run(); err != nil {
return "", fmt.Errorf("error while starting the creation of CloudInit's ISO image: %s", err)
return "", fmt.Errorf("error while starting the creation of CloudInit's ISO image: %w", err)
}
log.Printf("ISO created at %s", isoDestination)
@ -174,20 +174,19 @@ func (ci *defCloudInit) createFiles() (string, error) {
log.Print("Creating ISO contents")
tmpDir, err := os.MkdirTemp("", "cloudinit")
if err != nil {
return "", fmt.Errorf("cannot create tmp directory for cloudinit ISO generation: %s",
err)
return "", fmt.Errorf("cannot create tmp directory for cloudinit ISO generation: %w", err)
}
// user-data
if err = os.WriteFile(filepath.Join(tmpDir, userDataFileName), []byte(ci.UserData), os.ModePerm); err != nil {
return "", fmt.Errorf("error while writing user-data to file: %s", err)
return "", fmt.Errorf("error while writing user-data to file: %w", err)
}
// meta-data
if err = os.WriteFile(filepath.Join(tmpDir, metaDataFileName), []byte(ci.MetaData), os.ModePerm); err != nil {
return "", fmt.Errorf("error while writing meta-data to file: %s", err)
return "", fmt.Errorf("error while writing meta-data to file: %w", err)
}
// network-config
if err = os.WriteFile(filepath.Join(tmpDir, networkConfigFileName), []byte(ci.NetworkConfig), os.ModePerm); err != nil {
return "", fmt.Errorf("error while writing network-config to file: %s", err)
return "", fmt.Errorf("error while writing network-config to file: %w", err)
}
log.Print("ISO contents created")
@ -210,10 +209,10 @@ func newCloudInitDefFromRemoteISO(_ context.Context, virConn *libvirt.Libvirt, i
return ci, fmt.Errorf("can't retrieve volume %s: %w", key, err)
}
err = ci.setCloudInitDiskNameFromExistingVol(virConn, volume)
if err != nil {
return ci, err
if volume.Name == "" {
return ci, fmt.Errorf("error retrieving cloudinit volume name for volume key: %s", volume.Key)
}
ci.Name = volume.Name
err = ci.setCloudInitPoolNameFromExistingVol(virConn, volume)
if err != nil {
@ -229,7 +228,7 @@ func newCloudInitDefFromRemoteISO(_ context.Context, virConn *libvirt.Libvirt, i
return ci, err
}
err = ci.setCloudInitDataFromExistingCloudInitDisk(virConn, isoFile)
err = ci.setCloudInitDataFromExistingCloudInitDisk(isoFile)
if err != nil {
return ci, err
}
@ -237,10 +236,10 @@ func newCloudInitDefFromRemoteISO(_ context.Context, virConn *libvirt.Libvirt, i
}
// setCloudInitDataFromExistingCloudInitDisk read and set UserData, MetaData, and NetworkConfig from existing CloudInitDisk.
func (ci *defCloudInit) setCloudInitDataFromExistingCloudInitDisk(virConn *libvirt.Libvirt, isoFile *os.File) error {
func (ci *defCloudInit) setCloudInitDataFromExistingCloudInitDisk(isoFile *os.File) error {
isoReader, err := iso9660.NewReader(isoFile)
if err != nil {
return fmt.Errorf("error initializing ISO reader: %s", err)
return fmt.Errorf("error initializing ISO reader: %w", err)
}
for {
@ -277,7 +276,7 @@ func (ci *defCloudInit) setCloudInitDataFromExistingCloudInitDisk(virConn *libvi
func (ci *defCloudInit) setCloudInitPoolNameFromExistingVol(virConn *libvirt.Libvirt, volume libvirt.StorageVol) error {
volPool, err := virConn.StoragePoolLookupByVolume(volume)
if err != nil {
return fmt.Errorf("error retrieving pool for cloudinit volume: %s", err)
return fmt.Errorf("error retrieving pool for cloudinit volume: %w", err)
}
if volPool.Name == "" {
@ -287,22 +286,12 @@ func (ci *defCloudInit) setCloudInitPoolNameFromExistingVol(virConn *libvirt.Lib
return nil
}
// FIXME Consider doing this inline.
// setCloudInitDisklNameFromVol retrieve CloudInitname from an existing CloudInitDisk.
func (ci *defCloudInit) setCloudInitDiskNameFromExistingVol(virConn *libvirt.Libvirt, volume libvirt.StorageVol) error {
if volume.Name == "" {
return fmt.Errorf("error retrieving cloudinit volume name for volume key: %s", volume.Key)
}
ci.Name = volume.Name
return nil
}
func readIso9660File(file os.FileInfo) ([]byte, error) {
log.Printf("ISO reader: processing file %s", file.Name())
dataBytes, err := io.ReadAll(file.Sys().(io.Reader))
if err != nil {
return nil, fmt.Errorf("error while reading %s: %s", file.Name(), err)
return nil, fmt.Errorf("error while reading %s: %w", file.Name(), err)
}
return dataBytes, nil
}
@ -314,26 +303,26 @@ func downloadISO(virConn *libvirt.Libvirt, volume libvirt.StorageVol) (*os.File,
// get Volume info (required to get size later)
_, size, _, err := virConn.StorageVolGetInfo(volume)
if err != nil {
return nil, fmt.Errorf("error retrieving info for volume: %s", err)
return nil, fmt.Errorf("error retrieving info for volume: %w", err)
}
// create tmp file for the ISO
tmpFile, err := os.CreateTemp("", "cloudinit")
if err != nil {
return nil, fmt.Errorf("cannot create tmp file: %s", err)
return nil, fmt.Errorf("cannot create tmp file: %w", err)
}
w := bufio.NewWriterSize(tmpFile, int(size))
// download ISO file
if err := virConn.StorageVolDownload(volume, w, 0, size, 0); err != nil {
return tmpFile, fmt.Errorf("error while downloading volume: %s", err)
return tmpFile, fmt.Errorf("error while downloading volume: %w", err)
}
bytesCopied := w.Buffered()
err = w.Flush()
if err != nil {
return tmpFile, fmt.Errorf("error while copying remote volume to local disk: %s", err)
return tmpFile, fmt.Errorf("error while copying remote volume to local disk: %w", err)
}
log.Printf("%d bytes downloaded", bytesCopied)
@ -341,7 +330,9 @@ func downloadISO(virConn *libvirt.Libvirt, volume libvirt.StorageVol) (*os.File,
return tmpFile, fmt.Errorf("error while copying remote volume to local disk, bytesCopied %d != %d volume.size", bytesCopied, size)
}
tmpFile.Seek(0, 0)
if _, err := tmpFile.Seek(0, 0); err != nil {
return nil, err
}
return tmpFile, nil
}

View File

@ -5,7 +5,6 @@ import (
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"strings"
@ -82,19 +81,19 @@ func (ign *defIgnition) CreateAndUpload(client *Client) (string, error) {
volumeDefXML, err := xml.Marshal(volumeDef)
if err != nil {
return "", fmt.Errorf("error serializing libvirt volume: %s", err)
return "", fmt.Errorf("error serializing libvirt volume: %w", err)
}
// create the volume
volume, err := virConn.StorageVolCreateXML(pool, string(volumeDefXML), 0)
if err != nil {
return "", fmt.Errorf("error creating libvirt volume for Ignition %s: %s", ign.Name, err)
return "", fmt.Errorf("error creating libvirt volume for Ignition %s: %w", ign.Name, err)
}
// upload ignition file
err = img.Import(newCopier(virConn, &volume, volumeDef.Capacity.Value), volumeDef)
if err != nil {
return "", fmt.Errorf("error while uploading ignition file %s: %s", img.String(), err)
return "", fmt.Errorf("error while uploading ignition file %s: %w", img.String(), err)
}
if volume.Key == "" {
@ -123,9 +122,9 @@ func getIgnitionVolumeKeyFromTerraformID(id string) (string, error) {
// to a temporary ignition file.
func (ign *defIgnition) createFile() (string, error) {
log.Print("Creating Ignition temporary file")
tempFile, err := ioutil.TempFile("", ign.Name)
tempFile, err := os.CreateTemp("", ign.Name)
if err != nil {
return "", fmt.Errorf("error creating tmp file: %v", err)
return "", fmt.Errorf("error creating tmp file: %w", err)
}
defer tempFile.Close()
@ -170,7 +169,7 @@ func newIgnitionDefFromRemoteVol(virConn *libvirt.Libvirt, id string) (defIgniti
volume, err := virConn.StorageVolLookupByKey(key)
if err != nil {
return ign, fmt.Errorf("can't retrieve volume %s: %v", key, err)
return ign, fmt.Errorf("can't retrieve volume %s: %w", key, err)
}
ign.Name = volume.Name

View File

@ -28,7 +28,7 @@ func randomWWN(strlen int) string {
const chars = "abcdef0123456789"
result := make([]byte, strlen)
for i := 0; i < strlen; i++ {
//lint:ignore G404 math.rand is enough for this
//nolint:gosec // math.rand is enough for this
result[i] = chars[rand.Intn(len(chars))]
}
return oui + string(result)

View File

@ -1,6 +1,7 @@
package libvirt
import (
"context"
"errors"
"fmt"
"log"
@ -23,7 +24,7 @@ const domWaitLeaseDone = "all-addresses-obtained"
var errDomainInvalidState = errors.New("invalid state for domain")
func domainWaitForLeases(virConn *libvirt.Libvirt, domain libvirt.Domain, waitForLeases []*libvirtxml.DomainInterface,
func domainWaitForLeases(ctx context.Context, virConn *libvirt.Libvirt, domain libvirt.Domain, waitForLeases []*libvirtxml.DomainInterface,
timeout time.Duration, rd *schema.ResourceData) error {
waitFunc := func() (interface{}, string, error) {
@ -67,11 +68,11 @@ func domainWaitForLeases(virConn *libvirt.Libvirt, domain libvirt.Domain, waitFo
Target: []string{domWaitLeaseDone},
Refresh: waitFunc,
Timeout: timeout,
MinTimeout: 10 * time.Second,
Delay: 5 * time.Second,
MinTimeout: resourceStateMinTimeout,
Delay: resourceStateDelay,
}
_, err := stateConf.WaitForState()
_, err := stateConf.WaitForStateContext(ctx)
log.Print("[DEBUG] wait-for-leases was successful")
return err
}
@ -88,7 +89,7 @@ func domainIfaceHasAddress(virConn *libvirt.Libvirt, domain libvirt.Domain, ifac
log.Printf("[DEBUG] waiting for network address for iface=%s\n", mac)
ifacesWithAddr, err := domainGetIfacesInfo(virConn, domain, rd)
if err != nil {
return false, false, fmt.Errorf("error retrieving interface addresses: %s", err)
return false, false, fmt.Errorf("error retrieving interface addresses: %w", err)
}
log.Printf("[DEBUG] ifaces with addresses: %+v\n", ifacesWithAddr)
@ -138,7 +139,7 @@ func domainGetState(virConn *libvirt.Libvirt, domain libvirt.Domain) (string, er
func domainIsRunning(virConn *libvirt.Libvirt, domain libvirt.Domain) (bool, error) {
state, _, err := virConn.DomainGetState(domain, 0)
if err != nil {
return false, fmt.Errorf("couldn't get state of domain: %s", err)
return false, fmt.Errorf("couldn't get state of domain: %w", err)
}
return libvirt.DomainState(state) == libvirt.DomainRunning, nil
@ -169,16 +170,7 @@ func domainGetIfacesInfo(virConn *libvirt.Libvirt, domain libvirt.Domain, rd *sc
var interfaces []libvirt.DomainInterface
interfaces, err = virConn.DomainInterfaceAddresses(domain, addrsrc, 0)
if err != nil {
switch virErr := err.(type) {
default:
return interfaces, fmt.Errorf("error retrieving interface addresses: %w", virErr)
case libvirt.Error:
// Agent can be unresponsive if being installed/setup
if addrsrc == uint32(libvirt.DomainInterfaceAddressesSrcLease) && virErr.Code != uint32(libvirt.ErrOperationInvalid) ||
addrsrc == uint32(libvirt.DomainInterfaceAddressesSrcAgent) && virErr.Code != uint32(libvirt.ErrAgentUnresponsive) {
return interfaces, fmt.Errorf("Error retrieving interface addresses: %w", err)
}
}
return interfaces, fmt.Errorf("error retrieving interface addresses: %w", err)
}
log.Printf("[DEBUG] Interfaces info obtained with libvirt API:\n%s\n", spew.Sdump(interfaces))
@ -204,11 +196,11 @@ func newDiskForCloudInit(virConn *libvirt.Libvirt, volumeKey string) (libvirtxml
diskVolume, err := virConn.StorageVolLookupByKey(volumeKey)
if err != nil {
return disk, fmt.Errorf("can't retrieve volume %s: %v", volumeKey, err)
return disk, fmt.Errorf("can't retrieve volume %s: %w", volumeKey, err)
}
diskVolumeFile, err := virConn.StorageVolGetPath(diskVolume)
if err != nil {
return disk, fmt.Errorf("error retrieving volume file: %s", err)
return disk, fmt.Errorf("error retrieving volume file: %w", err)
}
disk.Source = &libvirtxml.DomainDiskSource{
@ -322,8 +314,6 @@ func setGraphics(d *schema.ResourceData, domainDef *libvirtxml.Domain, arch stri
case "socket":
listener.Socket = &libvirtxml.DomainGraphicListenerSocket{}
}
} else {
listenType = "none"
}
switch graphicsType {
@ -488,7 +478,7 @@ func setDisks(d *schema.ResourceData, domainDef *libvirtxml.Domain, virConn *lib
if volumeKey, ok := d.GetOk(prefix + ".volume_id"); ok {
diskVolume, err := virConn.StorageVolLookupByKey(volumeKey.(string))
if err != nil {
return fmt.Errorf("can't retrieve volume %s: %v", volumeKey.(string), err)
return fmt.Errorf("can't retrieve volume %s: %w", volumeKey.(string), err)
}
diskPool, err := virConn.StoragePoolLookupByVolume(diskVolume)
@ -685,7 +675,7 @@ func setNetworkInterfaces(d *schema.ResourceData, domainDef *libvirtxml.Domain,
var err error
mac, err = randomMACAddress()
if err != nil {
return fmt.Errorf("error generating mac address: %s", err)
return fmt.Errorf("error generating mac address: %w", err)
}
}
netIface.MAC = &libvirtxml.DomainInterfaceMAC{
@ -860,12 +850,12 @@ func destroyDomainByUserRequest(virConn *libvirt.Libvirt, d *schema.ResourceData
log.Printf("Destroying libvirt domain %s", uuidString(domain.UUID))
state, _, err := virConn.DomainGetState(domain, 0)
if err != nil {
return fmt.Errorf("couldn't get info about domain: %s", err)
return fmt.Errorf("couldn't get info about domain: %w", err)
}
if libvirt.DomainState(state) == libvirt.DomainRunning || libvirt.DomainState(state) == libvirt.DomainPaused {
if err := virConn.DomainDestroy(domain); err != nil {
return fmt.Errorf("couldn't destroy libvirt domain: %s", err)
return fmt.Errorf("couldn't destroy libvirt domain: %w", err)
}
}

View File

@ -15,13 +15,13 @@ func getXMLDomainDefFromLibvirt(virConn *libvirt.Libvirt, domain libvirt.Domain)
domainXMLDesc, err := virConn.DomainGetXMLDesc(domain, 0)
if err != nil {
return libvirtxml.Domain{}, fmt.Errorf("error retrieving libvirt domain XML description: %s", err)
return libvirtxml.Domain{}, fmt.Errorf("error retrieving libvirt domain XML description: %w", err)
}
domainDef := newDomainDef()
err = xml.Unmarshal([]byte(domainXMLDesc), &domainDef)
if err != nil {
return libvirtxml.Domain{}, fmt.Errorf("error reading libvirt domain XML description: %s", err)
return libvirtxml.Domain{}, fmt.Errorf("error reading libvirt domain XML description: %w", err)
}
return domainDef, nil
@ -46,6 +46,7 @@ func newDomainDef() libvirtxml.Domain {
},
Memory: &libvirtxml.DomainMemory{
Unit: "MiB",
//nolint:mnd
Value: 512,
},
VCPU: &libvirtxml.DomainVCPU{

View File

@ -128,12 +128,12 @@ func getNetworkDef(state *terraform.State, name string, virConn *libvirt.Libvirt
}
networkXMLDesc, err := virConn.NetworkGetXMLDesc(network, 0)
if err != nil {
return &libvirtxml.Network{}, fmt.Errorf("Error retrieving libvirt network XML description: %s", err)
return &libvirtxml.Network{}, fmt.Errorf("Error retrieving libvirt network XML description: %w", err)
}
networkDef := libvirtxml.Network{}
err = xml.Unmarshal([]byte(networkXMLDesc), &networkDef)
if err != nil {
return &libvirtxml.Network{}, fmt.Errorf("Error reading libvirt network XML description: %s", err)
return &libvirtxml.Network{}, fmt.Errorf("Error reading libvirt network XML description: %w", err)
}
return &networkDef, nil
}
@ -181,7 +181,7 @@ func testAccCheckLibvirtNetworkDestroy(s *terraform.State) error {
_, err := virtConn.NetworkLookupByUUID(parseUUID(rs.Primary.ID))
if err == nil {
return fmt.Errorf(
"Error waiting for network (%s) to be destroyed: %s",
"Error waiting for network (%s) to be destroyed: %w",
rs.Primary.ID, err)
}
}

View File

@ -31,12 +31,13 @@ func waitForNetworkDestroyed(virConn *libvirt.Libvirt, uuidStr string) resource.
log.Printf("Waiting for network %s to be destroyed", uuidStr)
uuid := parseUUID(uuidStr)
_, err := virConn.NetworkLookupByUUID(uuid)
if err.(libvirt.Error).Code == uint32(libvirt.ErrNoNetwork) {
return virConn, "NOT-EXISTS", nil
if _, err := virConn.NetworkLookupByUUID(uuid); err != nil {
if isError(err, libvirt.ErrNoNetwork) {
return virConn, "NOT-EXISTS", nil
}
return virConn, "NOT-EXISTS", err
}
return virConn, "ACTIVE", err
return virConn, "ACTIVE", nil
}
}
@ -102,10 +103,11 @@ func getIPsFromResource(d *schema.ResourceData) ([]libvirtxml.NetworkIP, error)
return ipsPtrsLst, nil
}
//nolint:mnd
func getNetworkIPConfig(address string) (*libvirtxml.NetworkIP, *libvirtxml.NetworkDHCP, error) {
_, ipNet, err := net.ParseCIDR(address)
if err != nil {
return nil, nil, fmt.Errorf("error parsing addresses definition '%s': %s", address, err)
return nil, nil, fmt.Errorf("error parsing addresses definition '%s': %w", address, err)
}
ones, bits := ipNet.Mask.Size()
family := "ipv4"
@ -200,7 +202,7 @@ func getMTUFromResource(d *schema.ResourceData) *libvirtxml.NetworkMTU {
// getDNSMasqOptionFromResource returns a list of dnsmasq options
// from the network definition.
func getDNSMasqOptionFromResource(d *schema.ResourceData) ([]libvirtxml.NetworkDnsmasqOption, error) {
func getDNSMasqOptionFromResource(d *schema.ResourceData) []libvirtxml.NetworkDnsmasqOption {
var dnsmasqOption []libvirtxml.NetworkDnsmasqOption
dnsmasqOptionPrefix := "dnsmasq_options.0"
if dnsmasqOptionCount, ok := d.GetOk(dnsmasqOptionPrefix + ".options.#"); ok {
@ -215,5 +217,5 @@ func getDNSMasqOptionFromResource(d *schema.ResourceData) ([]libvirtxml.NetworkD
}
}
return dnsmasqOption, nil
return dnsmasqOption
}

View File

@ -36,12 +36,12 @@ func newDefNetworkFromXML(s string) (libvirtxml.Network, error) {
func getXMLNetworkDefFromLibvirt(virConn *libvirt.Libvirt, network libvirt.Network) (libvirtxml.Network, error) {
networkXMLDesc, err := virConn.NetworkGetXMLDesc(network, 0)
if err != nil {
return libvirtxml.Network{}, fmt.Errorf("error retrieving libvirt network XML description: %s", err)
return libvirtxml.Network{}, fmt.Errorf("error retrieving libvirt network XML description: %w", err)
}
networkDef := libvirtxml.Network{}
err = xml.Unmarshal([]byte(networkXMLDesc), &networkDef)
if err != nil {
return libvirtxml.Network{}, fmt.Errorf("error reading libvirt network XML description: %s", err)
return libvirtxml.Network{}, fmt.Errorf("error reading libvirt network XML description: %w", err)
}
return networkDef, nil
}
@ -140,7 +140,7 @@ func updateOrAddHost(virConn *libvirt.Libvirt, n libvirt.Network, ip, mac, name
err = updateHost(virConn, n, ip, mac, name, xmlIdx)
// FIXME: libvirt.Error.DomainID is not available from library. Is it still required here?
// && virErr.Error.DomainID == uint32(.....FromNetwork) {
if virErr, ok := err.(libvirt.Error); ok && virErr.Code == uint32(libvirt.ErrOperationInvalid) {
if isError(err, libvirt.ErrOperationInvalid) {
log.Printf("[DEBUG]: karl: updateOrAddHost before addHost()\n")
return addHost(virConn, n, ip, mac, name, xmlIdx)
}

View File

@ -23,12 +23,12 @@ func updateDNSHosts(d *schema.ResourceData, meta interface{}, network libvirt.Ne
oldEntries, err := parseNetworkDNSHostsChange(oldInterface)
if err != nil {
return fmt.Errorf("parse old %s: %s", hostsKey, err)
return fmt.Errorf("parse old %s: %w", hostsKey, err)
}
newEntries, err := parseNetworkDNSHostsChange(newInterface)
if err != nil {
return fmt.Errorf("parse new %s: %s", hostsKey, err)
return fmt.Errorf("parse new %s: %w", hostsKey, err)
}
// process all the old DNS entries that must be removed
@ -46,13 +46,13 @@ func updateDNSHosts(d *schema.ResourceData, meta interface{}, network libvirt.Ne
data, err := xmlMarshallIndented(libvirtxml.NetworkDNSHost{IP: oldEntry.IP})
if err != nil {
return fmt.Errorf("serialize update: %s", err)
return fmt.Errorf("serialize update: %w", err)
}
err = virConn.NetworkUpdateCompat(network, libvirt.NetworkUpdateCommandDelete,
libvirt.NetworkSectionDNSHost, -1, data, libvirt.NetworkUpdateAffectLive|libvirt.NetworkUpdateAffectConfig)
if err != nil {
return fmt.Errorf("delete %s: %s", oldEntry.IP, err)
return fmt.Errorf("delete %s: %w", oldEntry.IP, err)
}
}
@ -71,13 +71,13 @@ func updateDNSHosts(d *schema.ResourceData, meta interface{}, network libvirt.Ne
data, err := xmlMarshallIndented(newEntry)
if err != nil {
return fmt.Errorf("serialize update: %s", err)
return fmt.Errorf("serialize update: %w", err)
}
err = virConn.NetworkUpdateCompat(network, libvirt.NetworkUpdateCommandAddLast,
libvirt.NetworkSectionDNSHost, -1, data, libvirt.NetworkUpdateAffectLive|libvirt.NetworkUpdateAffectConfig)
if err != nil {
return fmt.Errorf("add %v: %s", newEntry, err)
return fmt.Errorf("add %v: %w", newEntry, err)
}
}
}
@ -202,14 +202,14 @@ func getDNSForwardersFromResource(d *schema.ResourceData) ([]libvirtxml.NetworkD
// getDNSEnableFromResource returns string to enable ("yes") or disable ("no") dns
// in the network definition.
func getDNSEnableFromResource(d *schema.ResourceData) (string, error) {
func getDNSEnableFromResource(d *schema.ResourceData) string {
if dnsEnabled, ok := d.GetOk(dnsPrefix + ".enabled"); ok {
if dnsEnabled.(bool) {
return "yes", nil // this "boolean" must be "yes"|"no"
return "yes" // this "boolean" must be "yes"|"no"
}
return "no", nil
return "no"
}
return "", nil
return ""
}
// getDNSSRVFromResource returns a list of libvirt's DNS SRVs

View File

@ -26,7 +26,7 @@ func getRoutesFromResource(d *schema.ResourceData) ([]libvirtxml.NetworkRoute, e
if cidr, ok := d.GetOk(routePrefix + ".cidr"); ok {
addr, net, err := net.ParseCIDR(cidr.(string))
if err != nil {
return nil, fmt.Errorf("error parsing static route in network: %s", err)
return nil, fmt.Errorf("error parsing static route in network: %w", err)
}
if addr.To4() == nil {

View File

@ -3,15 +3,14 @@ package libvirt
import (
"context"
"log"
"time"
libvirt "github.com/digitalocean/go-libvirt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)
const (
poolExistsID = "EXISTS"
poolNotExistsID = "NOT-EXISTS"
poolStateExists = "EXISTS"
poolStateNotExists = "NOT-EXISTS"
)
// poolExists returns "EXISTS" or "NOT-EXISTS" depending on the current pool existence.
@ -21,11 +20,11 @@ func poolStateRefreshFunc(virConn *libvirt.Libvirt, uuid libvirt.UUID) resource.
if err != nil {
if isError(err, libvirt.ErrNoStoragePool) {
log.Printf("pool %s does not exist", uuid)
return virConn, poolNotExistsID, nil
return virConn, poolStateNotExists, nil
}
return virConn, poolNotExistsID, err
return virConn, poolStateNotExists, err
}
return virConn, poolExistsID, err
return virConn, poolStateExists, err
}
}
@ -33,12 +32,12 @@ func poolStateRefreshFunc(virConn *libvirt.Libvirt, uuid libvirt.UUID) resource.
func waitForStatePoolExists(ctx context.Context, virConn *libvirt.Libvirt, uuid libvirt.UUID) error {
log.Printf("Waiting for pool %s to appear...", uuid)
stateConf := &resource.StateChangeConf{
Pending: []string{poolNotExistsID},
Target: []string{poolExistsID},
Pending: []string{poolStateNotExists},
Target: []string{poolStateExists},
Refresh: poolStateRefreshFunc(virConn, uuid),
Timeout: 1 * time.Minute,
Delay: 5 * time.Second,
MinTimeout: 3 * time.Second,
Timeout: resourceStateTimeout,
Delay: resourceStateDelay,
MinTimeout: resourceStateMinTimeout,
}
if _, err := stateConf.WaitForStateContext(ctx); err != nil {
@ -51,12 +50,12 @@ func waitForStatePoolExists(ctx context.Context, virConn *libvirt.Libvirt, uuid
func waitForStatePoolDeleted(ctx context.Context, virConn *libvirt.Libvirt, uuid libvirt.UUID) error {
log.Printf("waiting for pool %s to be deleted...", uuid)
stateConf := &resource.StateChangeConf{
Pending: []string{poolExistsID},
Target: []string{poolNotExistsID},
Pending: []string{poolStateExists},
Target: []string{poolStateNotExists},
Refresh: poolStateRefreshFunc(virConn, uuid),
Timeout: 1 * time.Minute,
Delay: 5 * time.Second,
MinTimeout: 3 * time.Second,
Timeout: resourceStateTimeout,
Delay: resourceStateDelay,
MinTimeout: resourceStateMinTimeout,
}
if _, err := stateConf.WaitForStateContext(ctx); err != nil {

View File

@ -2,7 +2,6 @@ package libvirt
import (
"context"
"fmt"
"log"
libvirt "github.com/digitalocean/go-libvirt"
@ -111,28 +110,3 @@ func resourceCloudInitDiskDelete(ctx context.Context, d *schema.ResourceData, me
return diag.FromErr(volumeDelete(ctx, client, key))
}
func resourceCloudInitDiskExists(d *schema.ResourceData, meta interface{}) (bool, error) {
log.Printf("[DEBUG] Check if resource libvirt_cloudinit_disk exists")
client := meta.(*Client)
if client.libvirt == nil {
return false, fmt.Errorf(LibVirtConIsNil)
}
key, err := getCloudInitVolumeKeyFromTerraformID(d.Id())
if err != nil {
return false, err
}
volPoolName := d.Get("pool").(string)
volume, err := volumeLookupReallyHard(client, volPoolName, key)
if err != nil {
return false, err
}
if volume == nil {
return false, nil
}
return true, nil
}

View File

@ -48,7 +48,7 @@ func TestAccLibvirtCloudInit_CreateCloudInitDiskAndUpdate(t *testing.T) {
resource.TestCheckResourceAttr(
"libvirt_cloudinit_disk."+randomResourceName, "name", randomIsoName),
testAccCheckCloudInitVolumeExists("libvirt_cloudinit_disk."+randomResourceName, &volume),
expectedContents.testAccCheckCloudInitDiskFilesContent("libvirt_cloudinit_disk."+randomResourceName, &volume),
expectedContents.testAccCheckCloudInitDiskFilesContent("libvirt_cloudinit_disk."+randomResourceName),
),
},
{
@ -70,7 +70,7 @@ func TestAccLibvirtCloudInit_CreateCloudInitDiskAndUpdate(t *testing.T) {
resource.TestCheckResourceAttr(
"libvirt_cloudinit_disk."+randomResourceName, "name", randomIsoName),
testAccCheckCloudInitVolumeExists("libvirt_cloudinit_disk."+randomResourceName, &volume),
expectedContents2.testAccCheckCloudInitDiskFilesContent("libvirt_cloudinit_disk."+randomResourceName, &volume),
expectedContents2.testAccCheckCloudInitDiskFilesContent("libvirt_cloudinit_disk."+randomResourceName),
),
},
{
@ -89,7 +89,7 @@ func TestAccLibvirtCloudInit_CreateCloudInitDiskAndUpdate(t *testing.T) {
resource.TestCheckResourceAttr(
"libvirt_cloudinit_disk."+randomResourceName, "name", randomIsoName),
testAccCheckCloudInitVolumeExists("libvirt_cloudinit_disk."+randomResourceName, &volume),
expectedContentsEmpty.testAccCheckCloudInitDiskFilesContent("libvirt_cloudinit_disk."+randomResourceName, &volume),
expectedContentsEmpty.testAccCheckCloudInitDiskFilesContent("libvirt_cloudinit_disk."+randomResourceName),
),
},
// when we apply 2 times with same conf, we should not have a diff. See bug:
@ -112,7 +112,7 @@ func TestAccLibvirtCloudInit_CreateCloudInitDiskAndUpdate(t *testing.T) {
resource.TestCheckResourceAttr(
"libvirt_cloudinit_disk."+randomResourceName, "name", randomIsoName),
testAccCheckCloudInitVolumeExists("libvirt_cloudinit_disk."+randomResourceName, &volume),
expectedContentsEmpty.testAccCheckCloudInitDiskFilesContent("libvirt_cloudinit_disk."+randomResourceName, &volume),
expectedContentsEmpty.testAccCheckCloudInitDiskFilesContent("libvirt_cloudinit_disk."+randomResourceName),
),
},
},
@ -210,7 +210,7 @@ type Expected struct {
UserData, NetworkConfig, MetaData string
}
func (expected *Expected) testAccCheckCloudInitDiskFilesContent(volumeName string, volume *libvirt.StorageVol) resource.TestCheckFunc {
func (expected *Expected) testAccCheckCloudInitDiskFilesContent(volumeName string) resource.TestCheckFunc {
return func(state *terraform.State) error {
virConn := testAccProvider.Meta().(*Client).libvirt

View File

@ -107,7 +107,7 @@ func testAccCheckLibvirtIgnitionDestroy(s *terraform.State) error {
_, err := virtConn.StorageVolLookupByKey(ignKey)
if err == nil {
return fmt.Errorf(
"Error waiting for IgnitionVolume (%s) to be destroyed: %s",
"Error waitiEng for IgnitionVolume (%s) to be destroyed: %w",
ignKey, err)
}
}

View File

@ -1,6 +1,7 @@
package libvirt
import (
"context"
"encoding/xml"
"fmt"
"log"
@ -12,6 +13,7 @@ import (
"github.com/davecgh/go-spew/spew"
libvirt "github.com/digitalocean/go-libvirt"
"github.com/dmacvicar/terraform-provider-libvirt/libvirt/helper/suppress"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"libvirt.org/go/libvirtxml"
)
@ -28,10 +30,10 @@ func init() {
func resourceLibvirtDomain() *schema.Resource {
return &schema.Resource{
Create: resourceLibvirtDomainCreate,
Read: resourceLibvirtDomainRead,
Delete: resourceLibvirtDomainDelete,
Update: resourceLibvirtDomainUpdate,
CreateContext: resourceLibvirtDomainCreate,
ReadContext: resourceLibvirtDomainRead,
DeleteContext: resourceLibvirtDomainDelete,
UpdateContext: resourceLibvirtDomainUpdate,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
@ -63,6 +65,7 @@ func resourceLibvirtDomain() *schema.Resource {
"memory": {
Type: schema.TypeInt,
Optional: true,
//nolint:mnd
Default: 512,
ForceNew: true,
},
@ -466,17 +469,17 @@ func resourceLibvirtDomain() *schema.Resource {
}
}
func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error {
func resourceLibvirtDomainCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
log.Printf("[DEBUG] Create resource libvirt_domain")
virConn := meta.(*Client).libvirt
if virConn == nil {
return fmt.Errorf(LibVirtConIsNil)
return diag.Errorf(LibVirtConIsNil)
}
domainDef, err := newDomainDefForConnection(virConn, d)
if err != nil {
return err
return diag.FromErr(err)
}
if name, ok := d.GetOk("name"); ok {
@ -507,11 +510,11 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
arch, err := getHostArchitecture(virConn)
if err != nil {
return fmt.Errorf("error retrieving host architecture: %s", err)
return diag.Errorf("error retrieving host architecture: %s", err)
}
if err := setGraphics(d, &domainDef, arch); err != nil {
return err
return diag.FromErr(err)
}
setVideo(d, &domainDef)
@ -522,48 +525,48 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
setTPMs(d, &domainDef)
if err := setCoreOSIgnition(d, &domainDef, arch); err != nil {
return err
return diag.FromErr(err)
}
if err := setDisks(d, &domainDef, virConn); err != nil {
return err
return diag.FromErr(err)
}
if err := setFilesystems(d, &domainDef); err != nil {
return err
return diag.FromErr(err)
}
if err := setCloudinit(d, &domainDef, virConn); err != nil {
return err
return diag.FromErr(err)
}
var waitForLeases []*libvirtxml.DomainInterface
partialNetIfaces := make(map[string]*pendingMapping, d.Get("network_interface.#").(int))
if err := setNetworkInterfaces(d, &domainDef, virConn, partialNetIfaces, &waitForLeases); err != nil {
return err
return diag.FromErr(err)
}
connectURI, err := virConn.ConnectGetUri()
if err != nil {
return fmt.Errorf("error retrieving libvirt connection URI: %s", err)
return diag.Errorf("error retrieving libvirt connection URI: %s", err)
}
log.Printf("[INFO] Creating libvirt domain at %s", connectURI)
data, err := xmlMarshallIndented(domainDef)
if err != nil {
return fmt.Errorf("error serializing libvirt domain: %s", err)
return diag.Errorf("error serializing libvirt domain: %s", err)
}
log.Printf("[DEBUG] Generated XML for libvirt domain:\n%s", data)
data, err = transformResourceXML(data, d)
if err != nil {
return fmt.Errorf("error applying XSLT stylesheet: %s", err)
return diag.Errorf("error applying XSLT stylesheet: %s", err)
}
domain, err := virConn.DomainDefineXML(data)
if err != nil {
return fmt.Errorf("error defining libvirt domain: %s", err)
return diag.Errorf("error defining libvirt domain: %s", err)
}
if autostart, ok := d.GetOk("autostart"); ok {
@ -573,13 +576,13 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
}
err = virConn.DomainSetAutostart(domain, autostartInt)
if err != nil {
return fmt.Errorf("error setting autostart for domain: %s", err)
return diag.Errorf("error setting autostart for domain: %s", err)
}
}
err = virConn.DomainCreate(domain)
if err != nil {
return fmt.Errorf("error creating libvirt domain: %s", err)
return diag.Errorf("error creating libvirt domain: %s", err)
}
id := uuidString(domain.UUID)
@ -587,7 +590,7 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
log.Printf("[INFO] Domain ID: %s", d.Id())
if len(waitForLeases) > 0 {
err = domainWaitForLeases(virConn, domain, waitForLeases, d.Timeout(schema.TimeoutCreate), d)
err = domainWaitForLeases(ctx, virConn, domain, waitForLeases, d.Timeout(schema.TimeoutCreate), d)
if err != nil {
ipNotFoundMsg := "Please check following: \n" +
"1) is the domain running proplerly? \n" +
@ -596,16 +599,15 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
"4) is DHCP enabled on this Domain's network? \n" +
"5) if you use bridge network, the domain should have the pkg qemu-agent installed \n" +
"IMPORTANT: This error is not a terraform libvirt-provider error, but an error caused by your KVM/libvirt infrastructure configuration/setup"
return fmt.Errorf("couldn't retrieve IP address of domain id: %s. %s \n %s", d.Id(), ipNotFoundMsg, err)
return diag.Errorf("couldn't retrieve IP address of domain id: %s. %s \n %s", d.Id(), ipNotFoundMsg, err)
}
}
// We save runnig state to not mix what we have and what we want
requiredStatus := d.Get("running")
err = resourceLibvirtDomainRead(d, meta)
if err != nil {
return err
if diag := resourceLibvirtDomainRead(ctx, d, meta); diag.HasError() {
return diag
}
d.Set("running", requiredStatus)
@ -644,62 +646,60 @@ func resourceLibvirtDomainCreate(d *schema.ResourceData, meta interface{}) error
}
if err := destroyDomainByUserRequest(virConn, d, domain); err != nil {
return err
return diag.FromErr(err)
}
return nil
}
func resourceLibvirtDomainUpdate(d *schema.ResourceData, meta interface{}) error {
func resourceLibvirtDomainUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
log.Printf("[DEBUG] Update resource libvirt_domain")
virConn := meta.(*Client).libvirt
if virConn == nil {
return fmt.Errorf(LibVirtConIsNil)
return diag.Errorf(LibVirtConIsNil)
}
uuid := parseUUID(d.Id())
domain, err := virConn.DomainLookupByUUID(uuid)
if err != nil {
return fmt.Errorf("error retrieving libvirt domain by update: %s", err)
return diag.Errorf("error retrieving libvirt domain by update: %s", err)
}
domainRunningNow, err := domainIsRunning(virConn, domain)
if err != nil {
return err
return diag.FromErr(err)
}
if !domainRunningNow {
err = virConn.DomainCreate(domain)
if err != nil {
return fmt.Errorf("error creating libvirt domain: %s", err)
return diag.Errorf("error creating libvirt domain: %s", err)
}
}
d.Partial(true)
if d.HasChange("cloudinit") {
cloudinitID, err := getCloudInitVolumeKeyFromTerraformID(d.Get("cloudinit").(string))
if err != nil {
return err
return diag.FromErr(err)
}
disk, err := newDiskForCloudInit(virConn, cloudinitID)
if err != nil {
return err
return diag.FromErr(err)
}
data, err := xml.Marshal(disk)
if err != nil {
return fmt.Errorf("error serializing cloudinit disk: %s", err)
return diag.Errorf("error serializing cloudinit disk: %s", err)
}
err = virConn.DomainUpdateDeviceFlags(domain,
string(data),
libvirt.DomainDeviceModifyConfig|libvirt.DomainDeviceModifyCurrent|libvirt.DomainDeviceModifyLive)
if err != nil {
return fmt.Errorf("error while changing the cloudinit volume: %s", err)
return diag.Errorf("error while changing the cloudinit volume: %s", err)
}
}
@ -711,7 +711,7 @@ func resourceLibvirtDomainUpdate(d *schema.ResourceData, meta interface{}) error
err = virConn.DomainSetAutostart(domain, autoStart)
if err != nil {
return fmt.Errorf("error setting autostart for domain: %s", err)
return diag.Errorf("error setting autostart for domain: %s", err)
}
}
@ -730,7 +730,7 @@ func resourceLibvirtDomainUpdate(d *schema.ResourceData, meta interface{}) error
network, err := virConn.NetworkLookupByUUID(uuid)
if err != nil {
return fmt.Errorf("can't retrieve network ID %s", networkUUID)
return diag.Errorf("can't retrieve network ID %s", networkUUID)
}
hostname := d.Get(prefix + ".hostname").(string)
@ -741,28 +741,27 @@ func resourceLibvirtDomainUpdate(d *schema.ResourceData, meta interface{}) error
ip := net.ParseIP(address)
if ip == nil {
return fmt.Errorf("could not parse addresses '%s'", address)
return diag.Errorf("could not parse addresses '%s'", address)
}
log.Printf("[INFO] Updating IP/MAC/host=%s/%s/%s in '%s' network", ip.String(), mac, hostname, network.Name)
if err := updateOrAddHost(virConn, network, ip.String(), mac, hostname); err != nil {
return err
return diag.FromErr(err)
}
}
}
}
d.Partial(false)
return nil
}
func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
func resourceLibvirtDomainRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
log.Printf("[DEBUG] Read resource libvirt_domain")
virConn := meta.(*Client).libvirt
if virConn == nil {
return fmt.Errorf(LibVirtConIsNil)
return diag.Errorf(LibVirtConIsNil)
}
uuid := parseUUID(d.Id())
@ -773,35 +772,35 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
d.SetId("")
return nil
}
return fmt.Errorf("error retrieving libvirt domain: %w", err)
return diag.Errorf("error retrieving libvirt domain: %s", err)
}
xmlDesc, err := virConn.DomainGetXMLDesc(domain, 0)
if err != nil {
return fmt.Errorf("error retrieving libvirt domain XML description: %s", err)
return diag.Errorf("error retrieving libvirt domain XML description: %s", err)
}
log.Printf("[DEBUG] read: obtained XML desc for domain:\n%s", xmlDesc)
domainDef, err := newDomainDefForConnection(virConn, d)
if err != nil {
return err
return diag.FromErr(err)
}
err = xml.Unmarshal([]byte(xmlDesc), &domainDef)
if err != nil {
return fmt.Errorf("error reading libvirt domain XML description: %s", err)
return diag.Errorf("error reading libvirt domain XML description: %s", err)
}
autostart, err := virConn.DomainGetAutostart(domain)
if err != nil {
return fmt.Errorf("error reading domain autostart setting: %s", err)
return diag.Errorf("error reading domain autostart setting: %s", err)
}
_ = d.Set("autostart", autostart > 0)
domainRunningNow, err := domainIsRunning(virConn, domain)
if err != nil {
return fmt.Errorf("error reading domain running state : %s", err)
return diag.Errorf("error reading domain running state : %s", err)
}
d.Set("name", domainDef.Name)
@ -814,7 +813,7 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
case "MiB":
d.Set("memory", domainDef.Memory.Value)
default:
return fmt.Errorf("invalid memory unit : %s", domainDef.Memory.Unit)
return diag.Errorf("invalid memory unit : %s", domainDef.Memory.Unit)
}
if domainDef.OS.Loader != nil {
@ -849,22 +848,20 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
d.Set("arch", domainDef.OS.Type.Arch)
d.Set("running", domainRunningNow)
cmdLines, err := splitKernelCmdLine(domainDef.OS.Cmdline)
if err != nil {
return err
}
cmdLines := splitKernelCmdLine(domainDef.OS.Cmdline)
d.Set("cmdline", cmdLines)
d.Set("kernel", domainDef.OS.Kernel)
d.Set("initrd", domainDef.OS.Initrd)
caps, err := getHostCapabilities(virConn)
if err != nil {
return err
return diag.FromErr(err)
}
machine, err := getOriginalMachineName(caps, domainDef.OS.Type.Arch, domainDef.OS.Type.Type,
domainDef.OS.Type.Machine)
if err != nil {
return err
return diag.FromErr(err)
}
d.Set("machine", machine)
@ -879,7 +876,7 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
// network drives do not have a volume associated
if diskDef.Source.Network != nil {
if len(diskDef.Source.Network.Hosts) < 1 {
return fmt.Errorf("network disk does not contain any hosts")
return diag.Errorf("network disk does not contain any hosts")
}
url, err := url.Parse(fmt.Sprintf("%s://%s:%s%s",
diskDef.Source.Network.Protocol,
@ -887,7 +884,7 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
diskDef.Source.Network.Hosts[0].Port,
diskDef.Source.Network.Name))
if err != nil {
return err
return diag.FromErr(err)
}
disk = map[string]interface{}{
"url": url.String(),
@ -912,7 +909,7 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
// This code will be removed in future versions of the provider.
virVol, err := virConn.StorageVolLookupByPath(diskDef.Source.File.File)
if err != nil {
return fmt.Errorf("error retrieving volume for disk: %s", err)
return diag.Errorf("error retrieving volume for disk: %s", err)
}
disk = map[string]interface{}{
@ -921,12 +918,12 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
} else {
pool, err := virConn.StoragePoolLookupByName(diskDef.Source.Volume.Pool)
if err != nil {
return fmt.Errorf("error retrieving pool for disk: %s", err)
return diag.Errorf("error retrieving pool for disk: %s", err)
}
virVol, err := virConn.StorageVolLookupByName(pool, diskDef.Source.Volume.Volume)
if err != nil {
return fmt.Errorf("error retrieving volume for disk: %s", err)
return diag.Errorf("error retrieving volume for disk: %s", err)
}
disk = map[string]interface{}{
@ -966,7 +963,7 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
// lookup interfaces with addresses
ifacesWithAddr, err := domainGetIfacesInfo(virConn, domain, d)
if err != nil {
return fmt.Errorf("error retrieving interface addresses: %s", err)
return diag.Errorf("error retrieving interface addresses: %s", err)
}
addressesForMac := func(mac string) []string {
@ -1009,17 +1006,17 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
if networkInterfaceDef.Source.Network != nil {
network, err := virConn.NetworkLookupByName(networkInterfaceDef.Source.Network.Network)
if err != nil {
return fmt.Errorf("can't retrieve network ID for '%s'", networkInterfaceDef.Source.Network.Network)
return diag.Errorf("can't retrieve network ID for '%s'", networkInterfaceDef.Source.Network.Network)
}
netIface["network_id"] = uuidString(network.UUID)
if err != nil {
return fmt.Errorf("can't retrieve network ID for '%s'", networkInterfaceDef.Source.Network.Network)
return diag.Errorf("can't retrieve network ID for '%s'", networkInterfaceDef.Source.Network.Network)
}
networkDef, err := getXMLNetworkDefFromLibvirt(virConn, network)
if err != nil {
return err
return diag.FromErr(err)
}
netIface["network_name"] = networkInterfaceDef.Source.Network.Network
@ -1068,12 +1065,12 @@ func resourceLibvirtDomainRead(d *schema.ResourceData, meta interface{}) error {
return nil
}
func resourceLibvirtDomainDelete(d *schema.ResourceData, meta interface{}) error {
func resourceLibvirtDomainDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
log.Printf("[DEBUG] Delete resource libvirt_domain")
virConn := meta.(*Client).libvirt
if virConn == nil {
return fmt.Errorf(LibVirtConIsNil)
return diag.Errorf(LibVirtConIsNil)
}
log.Printf("[DEBUG] Deleting domain %s", d.Id())
@ -1082,43 +1079,43 @@ func resourceLibvirtDomainDelete(d *schema.ResourceData, meta interface{}) error
domain, err := virConn.DomainLookupByUUID(uuid)
if err != nil {
return fmt.Errorf("error retrieving libvirt domain by delete: %s", err)
return diag.Errorf("error retrieving libvirt domain by delete: %s", err)
}
xmlDesc, err := virConn.DomainGetXMLDesc(domain, 0)
if err != nil {
return fmt.Errorf("error retrieving libvirt domain XML description: %s", err)
return diag.Errorf("error retrieving libvirt domain XML description: %s", err)
}
domainDef, err := newDomainDefForConnection(virConn, d)
if err != nil {
return err
return diag.FromErr(err)
}
err = xml.Unmarshal([]byte(xmlDesc), &domainDef)
if err != nil {
return fmt.Errorf("error reading libvirt domain XML description: %s", err)
return diag.Errorf("error reading libvirt domain XML description: %s", err)
}
state, _, err := virConn.DomainGetState(domain, 0)
if err != nil {
return fmt.Errorf("couldn't get info about domain: %s", err)
return diag.Errorf("couldn't get info about domain: %s", err)
}
if state == int32(libvirt.DomainRunning) || state == int32(libvirt.DomainPaused) {
if err := virConn.DomainDestroy(domain); err != nil {
return fmt.Errorf("couldn't destroy libvirt domain: %s", err)
return diag.Errorf("couldn't destroy libvirt domain: %s", err)
}
}
if err := virConn.DomainUndefineFlags(domain, libvirt.DomainUndefineNvram|libvirt.DomainUndefineSnapshotsMetadata|libvirt.DomainUndefineManagedSave|libvirt.DomainUndefineCheckpointsMetadata); err != nil {
if e := err.(libvirt.Error); e.Code == uint32(libvirt.ErrNoSupport) || e.Code == uint32(libvirt.ErrInvalidArg) {
if isError(err, libvirt.ErrNoSupport) || isError(err, libvirt.ErrInvalidArg) {
log.Printf("libvirt does not support undefine flags: will try again without flags")
if err := virConn.DomainUndefine(domain); err != nil {
return fmt.Errorf("couldn't undefine libvirt domain: %s", err)
return diag.Errorf("couldn't undefine libvirt domain: %s", err)
}
} else {
return fmt.Errorf("couldn't undefine libvirt domain with flags: %s", err)
return diag.Errorf("couldn't undefine libvirt domain with flags: %s", err)
}
}

View File

@ -2,7 +2,6 @@ package libvirt
import (
"fmt"
"io/ioutil"
"log"
"net/url"
"os"
@ -151,7 +150,7 @@ func TestAccLibvirtDomain_Volume(t *testing.T) {
Config: configVolDettached,
Check: resource.ComposeTestCheckFunc(
testAccCheckLibvirtDomainExists("libvirt_domain."+randomDomainName, &domain),
testAccCheckLibvirtVolumeDoesNotExists("libvirt_volume."+randomVolumeName, &volume),
testAccCheckLibvirtVolumeDoesNotExists(&volume),
),
},
},
@ -161,6 +160,8 @@ func TestAccLibvirtDomain_Volume(t *testing.T) {
func TestAccLibvirtDomain_VolumeTwoDisks(t *testing.T) {
var domain libvirt.Domain
var volume libvirt.StorageVol
var volume2 libvirt.StorageVol
randomVolumeName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
randomVolumeName2 := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
randomDomainName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
@ -210,15 +211,15 @@ func TestAccLibvirtDomain_VolumeTwoDisks(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
testAccCheckLibvirtDomainExists("libvirt_domain."+randomDomainName, &domain),
testAccCheckLibvirtVolumeExists("libvirt_volume."+randomVolumeName, &volume),
testAccCheckLibvirtVolumeExists("libvirt_volume."+randomVolumeName2, &volume),
testAccCheckLibvirtVolumeExists("libvirt_volume."+randomVolumeName2, &volume2),
),
},
{
Config: configVolDettached,
Check: resource.ComposeTestCheckFunc(
testAccCheckLibvirtDomainExists("libvirt_domain."+randomDomainName, &domain),
testAccCheckLibvirtVolumeDoesNotExists("libvirt_volume."+randomVolumeName, &volume),
testAccCheckLibvirtVolumeDoesNotExists("libvirt_volume."+randomVolumeName2, &volume),
testAccCheckLibvirtVolumeDoesNotExists(&volume),
testAccCheckLibvirtVolumeDoesNotExists(&volume2),
),
},
},
@ -388,18 +389,12 @@ func TestAccLibvirtDomain_BlockDevice(t *testing.T) {
})
}
/* FIXME: Disable for now. It fails with:
unsupported configuration: disk type 'virtio' of 'vda' does not support ejectable media
func TestAccLibvirtDomain_URLDisk(t *testing.T) {
var domain libvirt.Domain
randomDomainName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
fws := fileWebServer{}
if err := fws.Start(); err != nil {
t.Fatal(err)
}
defer fws.Stop()
fws := newFileWebServer(t)
fws.Start()
defer fws.Close()
isoPath, err := filepath.Abs("testdata/tcl.iso")
if err != nil {
@ -439,7 +434,7 @@ func TestAccLibvirtDomain_URLDisk(t *testing.T) {
},
})
}*/
}
func TestAccLibvirtDomain_MultiISODisks(t *testing.T) {
var domain libvirt.Domain
@ -700,7 +695,7 @@ func TestAccLibvirtDomain_CheckDHCPEntries(t *testing.T) {
Check: resource.ComposeTestCheckFunc(
testAccCheckLibvirtDestroyLeavesIPs(
"libvirt_network."+randomNetworkName,
"192.0.0.2", &network,
"192.0.0.2",
),
),
},
@ -1030,7 +1025,7 @@ func testAccCheckIgnitionXML(domain *libvirt.Domain, volume *libvirt.StorageVol,
virConn := testAccProvider.Meta().(*Client).libvirt
domainDef, err := getXMLDomainDefFromLibvirt(virConn, *domain)
if err != nil {
return fmt.Errorf("Error retrieving libvirt domain XML description from existing domain: %s", err)
return fmt.Errorf("Error retrieving libvirt domain XML description from existing domain: %w", err)
}
if volume.Key == "" {
@ -1086,7 +1081,7 @@ func testAccCheckLibvirtDomainDescription(domain *libvirt.Domain, checkFunc func
virConn := testAccProvider.Meta().(*Client).libvirt
domainDef, err := getXMLDomainDefFromLibvirt(virConn, *domain)
if err != nil {
return fmt.Errorf("Error retrieving libvirt domain XML description from existing domain: %s", err)
return fmt.Errorf("Error retrieving libvirt domain XML description from existing domain: %w", err)
}
return checkFunc(domainDef)
}
@ -1098,7 +1093,7 @@ func testAccCheckLibvirtURLDisk(u *url.URL, domain *libvirt.Domain) resource.Tes
virConn := testAccProvider.Meta().(*Client).libvirt
domainDef, err := getXMLDomainDefFromLibvirt(virConn, *domain)
if err != nil {
return fmt.Errorf("Error getting libvirt XML definition from existing libvirt domain: %s", err)
return fmt.Errorf("Error getting libvirt XML definition from existing libvirt domain: %w", err)
}
disks := domainDef.Devices.Disks
@ -1129,7 +1124,7 @@ func testAccCheckLibvirtMultiISODisks(domain *libvirt.Domain) resource.TestCheck
virConn := testAccProvider.Meta().(*Client).libvirt
domainDef, err := getXMLDomainDefFromLibvirt(virConn, *domain)
if err != nil {
return fmt.Errorf("Error getting libvirt XML definition from existing libvirt domain: %s", err)
return fmt.Errorf("Error getting libvirt XML definition from existing libvirt domain: %w", err)
}
disks := domainDef.Devices.Disks
@ -1147,7 +1142,7 @@ func testAccCheckLibvirtMultiISODisks(domain *libvirt.Domain) resource.TestCheck
}
}
func testAccCheckLibvirtDestroyLeavesIPs(name string, ip string, network *libvirt.Network) resource.TestCheckFunc {
func testAccCheckLibvirtDestroyLeavesIPs(name string, ip string) resource.TestCheckFunc {
return func(state *terraform.State) error {
virConn := testAccProvider.Meta().(*Client).libvirt
@ -1172,7 +1167,7 @@ func testAccCheckLibvirtDomainKernelInitrdCmdline(domain *libvirt.Domain, kernel
virConn := testAccProvider.Meta().(*Client).libvirt
domainDef, err := getXMLDomainDefFromLibvirt(virConn, *domain)
if err != nil {
return fmt.Errorf("Error retrieving libvirt domain XML description from existing domain: %s", err)
return fmt.Errorf("Error retrieving libvirt domain XML description from existing domain: %w", err)
}
if kernel.Key == "" {
@ -1202,17 +1197,19 @@ func createTempBlockDev(devname string) (string, string, error) {
// Create a 1MB temp file
filename := filepath.Join(os.TempDir(), devname)
//nolint:gosec // G204 not sure why gosec complains but we should replace dd call
cmd := exec.Command("dd", "if=/dev/zero", "of="+filename, "bs=1024", "count=1024")
fmt.Printf("Executing command: %s\n", strings.Join(cmd.Args, " "))
if err := cmd.Run(); err != nil {
return "", "", fmt.Errorf("Error creating file %s: %s", filename, err)
return "", "", fmt.Errorf("Error creating file %s: %w", filename, err)
}
// Format the file
cmd = exec.Command("/sbin/mkfs.ext4", "-F", "-q", filename)
fmt.Printf("Executing command: %s\n", strings.Join(cmd.Args, " "))
if err := cmd.Run(); err != nil {
return "", "", fmt.Errorf("Error formatting file system: %s", err)
return "", "", fmt.Errorf("Error formatting file system: %w", err)
}
// Find an available loop device
@ -1220,7 +1217,7 @@ func createTempBlockDev(devname string) (string, string, error) {
loopdevStr, err := cmd.Output()
fmt.Printf("Executing command: %s\n", strings.Join(cmd.Args, " "))
if err != nil {
return "", "", fmt.Errorf("Error searching for available loop device: %s", err)
return "", "", fmt.Errorf("Error searching for available loop device: %w", err)
}
loopdev := strings.TrimRight(string(loopdevStr), "\n")
@ -1228,14 +1225,14 @@ func createTempBlockDev(devname string) (string, string, error) {
cmd = exec.Command("sudo", "chown", "--reference", filename, loopdev)
fmt.Printf("Executing command: %s\n", strings.Join(cmd.Args, " "))
if err := cmd.Run(); err != nil {
return "", "", fmt.Errorf("Error copying permissions from %s: %s", filename, err)
return "", "", fmt.Errorf("Error copying permissions from %s: %w", filename, err)
}
// Mount the file to a loop device
cmd = exec.Command("sudo", "/sbin/losetup", loopdev, filename)
fmt.Printf("Executing command: %s\n", strings.Join(cmd.Args, " "))
if err := cmd.Run(); err != nil {
return "", "", fmt.Errorf("Error setting up loop device: %s", err)
return "", "", fmt.Errorf("Error setting up loop device: %w", err)
}
log.Printf("Temporary file %s attached to loop device %s", filename, loopdev)
@ -1243,10 +1240,10 @@ func createTempBlockDev(devname string) (string, string, error) {
return filename, strings.TrimRight(string(loopdev), "\n"), nil
}
func createNvramFile(t *testing.T) (string, error) {
func createNvramFile(_ *testing.T) (string, error) {
// size of an accepted, valid, nvram backing store
nvramDummyBuffer := make([]byte, 131072)
file, err := ioutil.TempFile("", "nvram")
file, err := os.CreateTemp("", "nvram")
if err != nil {
return "", err
}
@ -1297,7 +1294,7 @@ func TestAccLibvirtDomainFirmware(t *testing.T) {
})
}
func subtestAccLibvirtDomainFirmwareNoTemplate(t *testing.T, NVRAMPath string, firmware string) {
func subtestAccLibvirtDomainFirmwareNoTemplate(t *testing.T, nvramPath string, firmware string) {
var domain libvirt.Domain
randomDomainName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
var config = fmt.Sprintf(`
@ -1307,7 +1304,7 @@ func subtestAccLibvirtDomainFirmwareNoTemplate(t *testing.T, NVRAMPath string, f
nvram {
file = "%s"
}
}`, randomDomainName, firmware, NVRAMPath)
}`, randomDomainName, firmware, nvramPath)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -1321,7 +1318,7 @@ func subtestAccLibvirtDomainFirmwareNoTemplate(t *testing.T, NVRAMPath string, f
resource.TestCheckResourceAttr(
"libvirt_domain."+randomDomainName, "name", "terraform-test-firmware-no-template"),
resource.TestCheckResourceAttr(
"libvirt_domain."+randomDomainName, "nvram.0.file", NVRAMPath),
"libvirt_domain."+randomDomainName, "nvram.0.file", nvramPath),
resource.TestCheckResourceAttr(
"libvirt_domain."+randomDomainName, "firmware", firmware),
),
@ -1330,7 +1327,7 @@ func subtestAccLibvirtDomainFirmwareNoTemplate(t *testing.T, NVRAMPath string, f
})
}
func subtestAccLibvirtDomainFirmwareTemplate(t *testing.T, NVRAMPath string, firmware string, template string) {
func subtestAccLibvirtDomainFirmwareTemplate(t *testing.T, nvramPath string, firmware string, template string) {
randomDomainName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
var domain libvirt.Domain
var config = fmt.Sprintf(`
@ -1341,7 +1338,7 @@ func subtestAccLibvirtDomainFirmwareTemplate(t *testing.T, NVRAMPath string, fir
file = "%s"
template = "%s"
}
}`, randomDomainName, firmware, NVRAMPath, template)
}`, randomDomainName, firmware, nvramPath, template)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
@ -1355,7 +1352,7 @@ func subtestAccLibvirtDomainFirmwareTemplate(t *testing.T, NVRAMPath string, fir
resource.TestCheckResourceAttr(
"libvirt_domain."+randomDomainName, "name", "terraform-test-firmware-with-template"),
resource.TestCheckResourceAttr(
"libvirt_domain."+randomDomainName, "nvram.0.file", NVRAMPath),
"libvirt_domain."+randomDomainName, "nvram.0.file", nvramPath),
resource.TestCheckResourceAttr(
"libvirt_domain."+randomDomainName, "nvram.0.template", template),
resource.TestCheckResourceAttr(
@ -1575,7 +1572,7 @@ func testAccCheckLibvirtDomainStateEqual(name string, domain *libvirt.Domain, ex
*domain = retrievedDomain
state, err := domainGetState(virConn, *domain)
if err != nil {
return fmt.Errorf("could not get domain state: %s", err)
return fmt.Errorf("could not get domain state: %w", err)
}
if state != exptectedState {
@ -1857,7 +1854,7 @@ func testAccCheckLibvirtDomainDestroy(s *terraform.State) error {
_, err := virConn.DomainLookupByUUID(parseUUID(rs.Primary.ID))
if err == nil {
return fmt.Errorf(
"Error waiting for domain (%s) to be destroyed: %s",
"Error waiting for domain (%s) to be destroyed: %w",
rs.Primary.ID, err)
}
}

View File

@ -1,13 +1,14 @@
package libvirt
import (
"context"
"fmt"
"log"
"net"
"strings"
"time"
libvirt "github.com/digitalocean/go-libvirt"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"libvirt.org/go/libvirtxml"
@ -40,10 +41,10 @@ const (
// check here: https://gitlab.com/search?utf8=%E2%9C%93&search=virNetworkDefUpdateNoSupport&group_id=130330&project_id=192693&search_code=true&repository_ref=master
func resourceLibvirtNetwork() *schema.Resource {
return &schema.Resource{
Create: resourceLibvirtNetworkCreate,
Read: resourceLibvirtNetworkRead,
Delete: resourceLibvirtNetworkDelete,
Update: resourceLibvirtNetworkUpdate,
CreateContext: resourceLibvirtNetworkCreate,
ReadContext: resourceLibvirtNetworkRead,
DeleteContext: resourceLibvirtNetworkDelete,
UpdateContext: resourceLibvirtNetworkUpdate,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
@ -290,77 +291,59 @@ func resourceLibvirtNetwork() *schema.Resource {
}
}
func resourceLibvirtNetworkExists(d *schema.ResourceData, meta interface{}) (bool, error) {
virConn := meta.(*Client).libvirt
if virConn == nil {
return false, fmt.Errorf(LibVirtConIsNil)
}
uuid := parseUUID(d.Id())
if _, err := virConn.NetworkLookupByUUID(uuid); err != nil {
// If the network couldn't be found, don't return an error otherwise
// Terraform won't create it again.
if lverr, ok := err.(libvirt.Error); ok && lverr.Code == uint32(libvirt.ErrNoNetwork) {
return false, nil
}
return false, err
}
return true, nil
}
// resourceLibvirtNetworkUpdate updates dynamically some attributes in the network.
func resourceLibvirtNetworkUpdate(d *schema.ResourceData, meta interface{}) error {
func resourceLibvirtNetworkUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
// check the list of things that can be changed dynamically
// in https://wiki.libvirt.org/page/Networking#virsh_net-update
virConn := meta.(*Client).libvirt
if virConn == nil {
return fmt.Errorf(LibVirtConIsNil)
return diag.Errorf(LibVirtConIsNil)
}
network, err := virConn.NetworkLookupByUUID(parseUUID(d.Id()))
uuid := parseUUID(d.Id())
network, err := virConn.NetworkLookupByUUID(uuid)
if err != nil {
return fmt.Errorf("can't retrieve network with ID '%s' during update: %s", d.Id(), err)
if isError(err, libvirt.ErrNoNetwork) {
d.SetId("")
return nil
}
return diag.Errorf("can't retrieve network with ID '%s' during update: %s", d.Id(), err)
}
d.Partial(true)
activeInt, err := virConn.NetworkIsActive(network)
if err != nil {
return fmt.Errorf("error when getting network %s status during update: %s", network.Name, err)
return diag.Errorf("error when getting network %s status during update: %s", network.Name, err)
}
active := activeInt == 1
if !active {
if activeInt != 1 {
log.Printf("[DEBUG] Activating network %s", network.Name)
if err := virConn.NetworkCreate(network); err != nil {
return fmt.Errorf("error when activating network %s during update: %s", network.Name, err)
return diag.Errorf("error when activating network %s during update: %s", network.Name, err)
}
}
if d.HasChange("autostart") {
err = virConn.NetworkSetAutostart(network, bool2int(d.Get("autostart").(bool)))
if err != nil {
return fmt.Errorf("error updating autostart for network %s: %s", network.Name, err)
return diag.Errorf("error updating autostart for network %s: %s", network.Name, err)
}
}
// detect changes in the DNS entries in this network
err = updateDNSHosts(d, meta, network)
if err != nil {
return fmt.Errorf("error updating DNS hosts for network %s: %s", network.Name, err)
return diag.Errorf("error updating DNS hosts for network %s: %s", network.Name, err)
}
d.Partial(false)
return nil
}
// resourceLibvirtNetworkCreate creates a libvirt network from the resource definition.
func resourceLibvirtNetworkCreate(d *schema.ResourceData, meta interface{}) error {
func resourceLibvirtNetworkCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
// see https://libvirt.org/formatnetwork.html
virConn := meta.(*Client).libvirt
if virConn == nil {
return fmt.Errorf(LibVirtConIsNil)
return diag.Errorf(LibVirtConIsNil)
}
networkDef := newNetworkDef()
@ -389,28 +372,25 @@ func resourceLibvirtNetworkCreate(d *schema.ResourceData, meta interface{}) erro
// if addresses are given set dhcp for these
ips, err := getIPsFromResource(d)
if err != nil {
return fmt.Errorf("could not set DHCP from adresses '%s'", err)
return diag.Errorf("could not set DHCP from adresses '%s'", err)
}
networkDef.IPs = ips
dnsEnabled, err := getDNSEnableFromResource(d)
if err != nil {
return err
}
dnsEnabled := getDNSEnableFromResource(d)
dnsForwarders, err := getDNSForwardersFromResource(d)
if err != nil {
return err
return diag.FromErr(err)
}
dnsSRVs, err := getDNSSRVFromResource(d)
if err != nil {
return err
return diag.FromErr(err)
}
dnsHosts, err := getDNSHostsFromResource(d)
if err != nil {
return err
return diag.FromErr(err)
}
dns := libvirtxml.NetworkDNS{
@ -423,17 +403,14 @@ func resourceLibvirtNetworkCreate(d *schema.ResourceData, meta interface{}) erro
} else if networkDef.Forward.Mode == netModeBridge {
if networkDef.Bridge.Name == "" {
return fmt.Errorf("'bridge' must be provided when using the bridged network mode")
return diag.Errorf("'bridge' must be provided when using the bridged network mode")
}
networkDef.Bridge.STP = ""
} else {
return fmt.Errorf("unsupported network mode '%s'", networkDef.Forward.Mode)
return diag.Errorf("unsupported network mode '%s'", networkDef.Forward.Mode)
}
dnsmasqOption, err := getDNSMasqOptionFromResource(d)
if err != nil {
return err
}
dnsmasqOption := getDNSMasqOptionFromResource(d)
dnsMasqOptions := libvirtxml.NetworkDnsmasqOptions{
Option: dnsmasqOption,
}
@ -442,7 +419,7 @@ func resourceLibvirtNetworkCreate(d *schema.ResourceData, meta interface{}) erro
// parse any static routes
routes, err := getRoutesFromResource(d)
if err != nil {
return err
return diag.FromErr(err)
}
networkDef.Routes = routes
@ -451,13 +428,13 @@ func resourceLibvirtNetworkCreate(d *schema.ResourceData, meta interface{}) erro
data, err := xmlMarshallIndented(networkDef)
if err != nil {
return fmt.Errorf("error serializing libvirt network: %s", err)
return diag.Errorf("error serializing libvirt network: %s", err)
}
log.Printf("[DEBUG] Generated XML for libvirt network:\n%s", data)
data, err = transformResourceXML(data, d)
if err != nil {
return fmt.Errorf("error applying XSLT stylesheet: %s", err)
return diag.Errorf("error applying XSLT stylesheet: %s", err)
}
network, err := func() (libvirt.Network, error) {
@ -471,7 +448,7 @@ func resourceLibvirtNetworkCreate(d *schema.ResourceData, meta interface{}) erro
}()
if err != nil {
return fmt.Errorf("error defining libvirt network: %s - %s", err, data)
return diag.Errorf("error defining libvirt network: %s - %s", err, data)
}
err = virConn.NetworkCreate(network)
@ -488,7 +465,7 @@ func resourceLibvirtNetworkCreate(d *schema.ResourceData, meta interface{}) erro
log.Printf("[WARNING] %v", err)
}
return fmt.Errorf("error creating libvirt network: %s", err)
return diag.Errorf("error creating libvirt network: %s", err)
}
id := uuidString(network.UUID)
d.SetId(id)
@ -499,33 +476,33 @@ func resourceLibvirtNetworkCreate(d *schema.ResourceData, meta interface{}) erro
Pending: []string{"BUILD"},
Target: []string{"ACTIVE"},
Refresh: waitForNetworkActive(virConn, network),
Timeout: 1 * time.Minute,
Delay: 5 * time.Second,
MinTimeout: 3 * time.Second,
Timeout: resourceStateTimeout,
Delay: resourceStateDelay,
MinTimeout: resourceStateMinTimeout,
}
_, err = stateConf.WaitForState()
_, err = stateConf.WaitForStateContext(ctx)
if err != nil {
return fmt.Errorf("error waiting for network to reach ACTIVE state: %s", err)
return diag.Errorf("error waiting for network to reach ACTIVE state: %s", err)
}
if autostart, ok := d.GetOk("autostart"); ok {
err = virConn.NetworkSetAutostart(network, bool2int(autostart.(bool)))
if err != nil {
return fmt.Errorf("error setting autostart for network: %s", err)
return diag.Errorf("error setting autostart for network: %s", err)
}
}
return resourceLibvirtNetworkRead(d, meta)
return resourceLibvirtNetworkRead(ctx, d, meta)
}
// resourceLibvirtNetworkRead gets the current resource from libvirt and creates
// the corresponding `schema.ResourceData`.
func resourceLibvirtNetworkRead(d *schema.ResourceData, meta interface{}) error {
func resourceLibvirtNetworkRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
log.Printf("[DEBUG] Read resource libvirt_network")
virConn := meta.(*Client).libvirt
if virConn == nil {
return fmt.Errorf(LibVirtConIsNil)
return diag.Errorf(LibVirtConIsNil)
}
uuid := parseUUID(d.Id())
@ -536,12 +513,12 @@ func resourceLibvirtNetworkRead(d *schema.ResourceData, meta interface{}) error
d.SetId("")
return nil
}
return fmt.Errorf("error retrieving libvirt network %w", err)
return diag.Errorf("error retrieving libvirt network %s", err)
}
networkDef, err := getXMLNetworkDefFromLibvirt(virConn, network)
if err != nil {
return fmt.Errorf("error reading libvirt network XML description: %s", err)
return diag.Errorf("error reading libvirt network XML description: %s", err)
}
d.Set("name", networkDef.Name)
@ -566,18 +543,19 @@ func resourceLibvirtNetworkRead(d *schema.ResourceData, meta interface{}) error
autostart, err := virConn.NetworkGetAutostart(network)
if err != nil {
return fmt.Errorf("error reading network autostart setting: %s", err)
return diag.Errorf("error reading network autostart setting: %s", err)
}
d.Set("autostart", autostart > 0)
// read add the IP addresses
addresses := []string{}
//nolint:mnd
for _, address := range networkDef.IPs {
// we get the host interface IP (ie, 10.10.8.1) but we want the network CIDR (ie, 10.10.8.0/24)
// so we need some transformations...
addr := net.ParseIP(address.Address)
if addr == nil {
return fmt.Errorf("error parsing IP '%s': %s", address.Address, err)
return diag.Errorf("error parsing IP '%s': %s", address.Address, err)
}
bits := net.IPv6len * 8
if addr.To4() != nil {
@ -677,10 +655,10 @@ func resourceLibvirtNetworkRead(d *schema.ResourceData, meta interface{}) error
return nil
}
func resourceLibvirtNetworkDelete(d *schema.ResourceData, meta interface{}) error {
func resourceLibvirtNetworkDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
virConn := meta.(*Client).libvirt
if virConn == nil {
return fmt.Errorf(LibVirtConIsNil)
return diag.Errorf(LibVirtConIsNil)
}
log.Printf("[DEBUG] Deleting network ID %s", d.Id())
@ -688,28 +666,28 @@ func resourceLibvirtNetworkDelete(d *schema.ResourceData, meta interface{}) erro
network, err := virConn.NetworkLookupByUUID(uuid)
if err != nil {
return fmt.Errorf("when destroying libvirt network: error retrieving %s", err)
return diag.Errorf("when destroying libvirt network: error retrieving %s", err)
}
activeInt, err := virConn.NetworkIsActive(network)
if err != nil {
return fmt.Errorf("couldn't determine if network is active: %s", err)
return diag.Errorf("couldn't determine if network is active: %s", err)
}
// network can be in 2 states, handles this case by case
if active := int2bool(int(activeInt)); active {
// network is active, so we need to destroy it and undefine it
if err := virConn.NetworkDestroy(network); err != nil {
return fmt.Errorf("when destroying libvirt network: %s", err)
return diag.Errorf("when destroying libvirt network: %s", err)
}
if err := virConn.NetworkUndefine(network); err != nil {
return fmt.Errorf("couldn't undefine libvirt network: %s", err)
return diag.Errorf("couldn't undefine libvirt network: %s", err)
}
} else {
// in case network is inactive just undefine it
if err := virConn.NetworkUndefine(network); err != nil {
return fmt.Errorf("couldn't undefine libvirt network: %s", err)
return diag.Errorf("couldn't undefine libvirt network: %s", err)
}
}
@ -717,13 +695,13 @@ func resourceLibvirtNetworkDelete(d *schema.ResourceData, meta interface{}) erro
Pending: []string{"ACTIVE"},
Target: []string{"NOT-EXISTS"},
Refresh: waitForNetworkDestroyed(virConn, d.Id()),
Timeout: 1 * time.Minute,
Delay: 5 * time.Second,
MinTimeout: 3 * time.Second,
Timeout: resourceStateTimeout,
Delay: resourceStateDelay,
MinTimeout: resourceStateMinTimeout,
}
_, err = stateConf.WaitForState()
_, err = stateConf.WaitForStateContext(ctx)
if err != nil {
return fmt.Errorf("error waiting for network to reach NOT-EXISTS state: %s", err)
return diag.Errorf("error waiting for network to reach NOT-EXISTS state: %s", err)
}
return nil
}

View File

@ -17,12 +17,12 @@ func testAccCheckLibvirtPoolExists(name string, pool *libvirt.StoragePool) resou
rs, err := getResourceFromTerraformState(name, state)
if err != nil {
return fmt.Errorf("Failed to get resource: %s", err)
return fmt.Errorf("Failed to get resource: %w", err)
}
retrievedPool, err := getPoolFromTerraformState(name, state, virConn)
if err != nil {
return fmt.Errorf("Failed to get pool: %s", err)
return fmt.Errorf("Failed to get pool: %w", err)
}
if uuidString(retrievedPool.UUID) == "" {
@ -39,25 +39,6 @@ func testAccCheckLibvirtPoolExists(name string, pool *libvirt.StoragePool) resou
}
}
func testAccCheckLibvirtPoolDoesNotExists(n string, pool *libvirt.StoragePool) resource.TestCheckFunc {
return func(s *terraform.State) error {
virConn := testAccProvider.Meta().(*Client).libvirt
id := pool.UUID
if uuidString(id) == "" {
return fmt.Errorf("UUID is blank")
}
_, err := virConn.StoragePoolLookupByUUID(id)
if err == nil {
return fmt.Errorf("Pool '%s' still exists", id)
}
return nil
}
}
func TestAccLibvirtPool_Import(t *testing.T) {
var pool libvirt.StoragePool
randomPoolResource := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
@ -89,7 +70,7 @@ func TestAccLibvirtPool_Import(t *testing.T) {
testImportStateCheckResourceAttr("libvirt_pool."+randomPoolResource, "type", "dir"),
testImportStateCheckResourceAttr("libvirt_pool."+randomPoolResource, "path", poolPath),
)(f); err != nil {
return fmt.Errorf("Check InstanceState n°%d / %d error: %s", i+1, len(instanceState), err)
return fmt.Errorf("Check InstanceState n°%d / %d error: %w", i+1, len(instanceState), err)
}
}
@ -110,7 +91,7 @@ func composeTestImportStateCheckFunc(fs ...ImportStateCheckFunc) ImportStateChec
return func(is *terraform.InstanceState) error {
for i, f := range fs {
if err := f(is); err != nil {
return fmt.Errorf("Check %d/%d error: %s", i+1, len(fs), err)
return fmt.Errorf("Check %d/%d error: %w", i+1, len(fs), err)
}
}
@ -202,7 +183,7 @@ func TestAccLibvirtPool_ManuallyDestroyed(t *testing.T) {
if err := client.libvirt.StoragePoolDestroy(pool); err != nil {
t.Errorf(err.Error())
}
if err := client.libvirt.StoragePoolDelete(pool, libvirt.StoragePoolDeleteNormal); err != nil {
t.Errorf(err.Error())
}
@ -278,7 +259,7 @@ func testAccCheckLibvirtPoolDestroy(state *terraform.State) error {
_, err := virConn.StoragePoolLookupByUUID(parseUUID(rs.Primary.ID))
if err == nil {
return fmt.Errorf(
"Error waiting for pool (%s) to be destroyed: %s",
"Error waiting for pool (%s) to be destroyed: %w",
rs.Primary.ID, err)
}
}

View File

@ -77,7 +77,7 @@ func resourceLibvirtVolume() *schema.Resource {
},
},
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
StateContext: schema.ImportStatePassthroughContext,
},
}
}

View File

@ -42,7 +42,7 @@ func testAccCheckLibvirtVolumeExists(name string, volume *libvirt.StorageVol) re
}
}
func testAccCheckLibvirtVolumeDoesNotExists(n string, volume *libvirt.StorageVol) resource.TestCheckFunc {
func testAccCheckLibvirtVolumeDoesNotExists(volume *libvirt.StorageVol) resource.TestCheckFunc {
return func(s *terraform.State) error {
virConn := testAccProvider.Meta().(*Client).libvirt
@ -58,7 +58,7 @@ func testAccCheckLibvirtVolumeDoesNotExists(n string, volume *libvirt.StorageVol
}
}
func testAccCheckLibvirtVolumeIsBackingStore(name string, volume *libvirt.StorageVol) resource.TestCheckFunc {
func testAccCheckLibvirtVolumeIsBackingStore(name string) resource.TestCheckFunc {
return func(state *terraform.State) error {
virConn := testAccProvider.Meta().(*Client).libvirt
@ -69,13 +69,13 @@ func testAccCheckLibvirtVolumeIsBackingStore(name string, volume *libvirt.Storag
volXMLDesc, err := virConn.StorageVolGetXMLDesc(*vol, 0)
if err != nil {
return fmt.Errorf("Error retrieving libvirt volume XML description: %s", err)
return fmt.Errorf("Error retrieving libvirt volume XML description: %w", err)
}
volumeDef := newDefVolume()
err = xml.Unmarshal([]byte(volXMLDesc), &volumeDef)
if err != nil {
return fmt.Errorf("Error reading libvirt volume XML description: %s", err)
return fmt.Errorf("Error reading libvirt volume XML description: %w", err)
}
if volumeDef.BackingStore == nil {
return fmt.Errorf("FAIL: the volume was supposed to be a backingstore, but it is not")
@ -127,9 +127,8 @@ func TestAccLibvirtVolume_Basic(t *testing.T) {
func TestAccLibvirtVolume_BackingStoreTestByID(t *testing.T) {
var volume libvirt.StorageVol
var volume2 libvirt.StorageVol
random := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
randomPoolPath := "/tmp/terraform-provider-libvirt-pool-" + random
randomPoolPath := t.TempDir()
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
@ -155,7 +154,7 @@ func TestAccLibvirtVolume_BackingStoreTestByID(t *testing.T) {
`, random, random, randomPoolPath, random, random, random, random, random, random, random),
Check: resource.ComposeTestCheckFunc(
testAccCheckLibvirtVolumeExists("libvirt_volume.backing-"+random, &volume),
testAccCheckLibvirtVolumeIsBackingStore("libvirt_volume."+random, &volume2),
testAccCheckLibvirtVolumeIsBackingStore("libvirt_volume."+random),
resource.TestCheckResourceAttr(
"libvirt_volume."+random, "size", "1073741824"),
),
@ -166,7 +165,6 @@ func TestAccLibvirtVolume_BackingStoreTestByID(t *testing.T) {
func TestAccLibvirtVolume_BackingStoreTestByName(t *testing.T) {
var volume libvirt.StorageVol
var volume2 libvirt.StorageVol
random := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha)
randomPoolPath := "/tmp/terraform-provider-libvirt-pool-" + random
resource.Test(t, resource.TestCase{
@ -194,7 +192,7 @@ func TestAccLibvirtVolume_BackingStoreTestByName(t *testing.T) {
`, random, random, randomPoolPath, random, random, random, random, random, random, random),
Check: resource.ComposeTestCheckFunc(
testAccCheckLibvirtVolumeExists("libvirt_volume.backing-"+random, &volume),
testAccCheckLibvirtVolumeIsBackingStore("libvirt_volume."+random, &volume2),
testAccCheckLibvirtVolumeIsBackingStore("libvirt_volume."+random),
resource.TestCheckResourceAttr(
"libvirt_volume."+random, "size", "1073741824"),
),
@ -500,7 +498,7 @@ func testAccCheckLibvirtVolumeDestroy(state *terraform.State) error {
_, err := virConn.StorageVolLookupByKey(rs.Primary.ID)
if err == nil {
return fmt.Errorf(
"Error waiting for volume (%s) to be destroyed: %s",
"Error waiting for volume (%s) to be destroyed: %w",
rs.Primary.ID, err)
}
}

11
libvirt/timeout.go Normal file
View File

@ -0,0 +1,11 @@
package libvirt
import (
"time"
)
const (
resourceStateTimeout = 1 * time.Minute
resourceStateDelay = 5 * time.Second
resourceStateMinTimeout = 3 * time.Second
)

View File

@ -2,7 +2,6 @@ package uri
import (
"net"
"time"
)
const (
@ -17,5 +16,5 @@ func (u *ConnectionURI) dialUNIX() (net.Conn, error) {
address = defaultUnixSock
}
return net.DialTimeout("unix", address, 2*time.Second)
return net.DialTimeout("unix", address, dialTimeout)
}

View File

@ -49,7 +49,7 @@ func waitForSuccess(errorMessage string, f func() error) error {
time.Sleep(WaitSleepInterval)
if time.Since(start) > WaitTimeout {
return fmt.Errorf("%s: %s", errorMessage, err)
return fmt.Errorf("%s: %w", errorMessage, err)
}
}
}

View File

@ -74,10 +74,10 @@ func getOriginalMachineName(caps libvirtxml.Caps, arch string, virttype string,
// as kernal args allow duplicate keys, we use a list of maps
// we jump to a next map as soon as we find a duplicate
// key.
func splitKernelCmdLine(cmdLine string) ([]map[string]string, error) {
func splitKernelCmdLine(cmdLine string) []map[string]string {
var cmdLines []map[string]string
if len(cmdLine) == 0 {
return cmdLines, nil
return cmdLines
}
currCmdLine := make(map[string]string)
@ -108,7 +108,7 @@ func splitKernelCmdLine(cmdLine string) ([]map[string]string, error) {
cl["_"] = strings.Join(keylessCmdLineArgs, " ")
cmdLines = append(cmdLines, cl)
}
return cmdLines, nil
return cmdLines
}
func getHostArchitecture(virConn *libvirt.Libvirt) (string, error) {

View File

@ -20,24 +20,18 @@ func TestSplitKernelCmdLine(t *testing.T) {
"key": "val",
"root": "UUID=aa52d618-a2c4-4aad-aeb7-68d9e3a2c91d"},
{"_": "nosplash rw"}}
r, err := splitKernelCmdLine("foo=bar foo=bar key=val root=UUID=aa52d618-a2c4-4aad-aeb7-68d9e3a2c91d nosplash rw")
r:= splitKernelCmdLine("foo=bar foo=bar key=val root=UUID=aa52d618-a2c4-4aad-aeb7-68d9e3a2c91d nosplash rw")
if !reflect.DeepEqual(r, e) {
t.Fatalf("got='%s' expected='%s'", spew.Sdump(r), spew.Sdump(e))
}
if err != nil {
t.Error(err)
}
}
func TestSplitKernelEmptyCmdLine(t *testing.T) {
var e []map[string]string
r, err := splitKernelCmdLine("")
r := splitKernelCmdLine("")
if !reflect.DeepEqual(r, e) {
t.Fatalf("got='%s' expected='%s'", spew.Sdump(r), spew.Sdump(e))
}
if err != nil {
t.Error(err)
}
}
func TestGetHostArchitecture(t *testing.T) {

View File

@ -6,15 +6,12 @@ import (
"net"
)
const (
maxIfaceNum = 100
)
// randomMACAddress returns a randomized MAC address
// with libvirt prefix.
//nolint:mnd
func randomMACAddress() (string, error) {
buf := make([]byte, 3)
//lint:ignore G404 math.rand is enough for this usecase
//nolint:gosec // math.rand is enough for this
if _, err := rand.Read(buf); err != nil {
return "", err
}
@ -33,15 +30,7 @@ func randomMACAddress() (string, error) {
buf[0], buf[1], buf[2]), nil
}
// randomPort returns a random port.
func randomPort() int {
const minPort = 1024
const maxPort = 65535
//lint:ignore G404 math.rand is enough for this usecase
return rand.Intn(maxPort-minPort) + minPort
}
//nolint:mnd
func getNetMaskWithMax16Bits(m net.IPMask) net.IPMask {
ones, bits := m.Size()

View File

@ -2,7 +2,6 @@ package libvirt
import (
"fmt"
"io/ioutil"
"net"
"net/http"
"net/http/httptest"
@ -48,7 +47,7 @@ func (fws *fileWebServer) Start() {
// Adds a file (with some content) in the directory served by the fileWebServer.
func (fws *fileWebServer) AddContent(content []byte) (string, *os.File, error) {
tmpfile, err := ioutil.TempFile(fws.Dir, "file-")
tmpfile, err := os.CreateTemp(fws.Dir, "file-")
if err != nil {
return "", nil, err
}

View File

@ -1,6 +1,7 @@
package libvirt
import (
"errors"
"fmt"
"io"
"log"
@ -22,11 +23,12 @@ func newCopier(virConn *libvirt.Libvirt, volume *libvirt.StorageVol, size uint64
// if we get unexpected EOF this mean that connection was closed suddently from server side
// the problem is not on the plugin but on server hosting currupted images
if err == io.ErrUnexpectedEOF {
if errors.Is(err, io.ErrUnexpectedEOF) {
return fmt.Errorf("error: transfer was unexpectedly closed from the server while downloading. Please try again later or check the server hosting sources")
}
if err != nil {
return fmt.Errorf("error while copying source to volume %s", err)
return fmt.Errorf("error while copying source to volume %w", err)
}
log.Printf("%d bytes uploaded\n", bytesCopied)
@ -46,7 +48,7 @@ func newCopier(virConn *libvirt.Libvirt, volume *libvirt.StorageVol, size uint64
*/
if err := virConn.StorageVolUpload(*volume, r, 0, size, 0); err != nil {
return fmt.Errorf("error while uploading volume %s", err)
return fmt.Errorf("error while uploading volume %w", err)
}
return nil

View File

@ -27,7 +27,7 @@ const (
// we specify the diff suppress function as the result of applying the identity
// transform to the xslt, stripping whitespace
// See https://www.terraform.io/docs/extend/schemas/schema-behaviors.html#diffsuppressfunc
func xsltDiffSupressFunc(k, old, new string, d *schema.ResourceData) bool {
func xsltDiffSupressFunc(_, old, new string, _ *schema.ResourceData) bool {
oldStrip, err := transformXML(old, identitySpaceStripXSLT)
if err != nil {
// fail, just use normal equality
@ -80,7 +80,7 @@ func transformXML(xmlS string, xsltS string) (string, error) {
return "", err
}
//lint:ignore G204 not sure why gosec complains
//nolint:gosec // G204 not sure why gosec complains
cmd := exec.Command("xsltproc",
"--nomkdir",
"--nonet",

View File

@ -4,7 +4,6 @@ import (
"context"
"fmt"
"log"
"time"
libvirt "github.com/digitalocean/go-libvirt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
@ -36,8 +35,8 @@ func waitForStateVolumeExists(ctx context.Context, virConn *libvirt.Libvirt, key
Pending: []string{volNotExistsID},
Target: []string{volExistsID},
Refresh: volumeExistsStateRefreshFunc(virConn, key),
Timeout: 1 * time.Minute,
MinTimeout: 3 * time.Second,
Timeout: resourceStateTimeout,
MinTimeout: resourceStateMinTimeout,
}
if _, err := stateConf.WaitForStateContext(ctx); err != nil {
@ -53,8 +52,8 @@ func volumeWaitDeleted(ctx context.Context, virConn *libvirt.Libvirt, key string
Pending: []string{volExistsID},
Target: []string{volNotExistsID},
Refresh: volumeExistsStateRefreshFunc(virConn, key),
Timeout: 1 * time.Minute,
MinTimeout: 3 * time.Second,
Timeout: resourceStateTimeout,
MinTimeout: resourceStateMinTimeout,
}
if _, err := stateConf.WaitForStateContext(ctx); err != nil {
@ -92,9 +91,11 @@ func volumeDelete(ctx context.Context, client *Client, key string) error {
client.poolMutexKV.Lock(volPool.Name)
defer client.poolMutexKV.Unlock(volPool.Name)
waitForSuccess("error refreshing pool for volume", func() error {
if err := waitForSuccess("error refreshing pool for volume", func() error {
return virConn.StoragePoolRefresh(volPool, 0)
})
}); err != nil {
return err
}
// Workaround for redhat#1293804
// https://bugzilla.redhat.com/show_bug.cgi?id=1293804#c12
@ -118,56 +119,3 @@ func volumeDelete(ctx context.Context, client *Client, key string) error {
return volumeWaitDeleted(ctx, client.libvirt, key)
}
// tries really hard to find volume with `key`
// it will try to start the pool if it does not find it
//
// Deprecated: only cloud init is using it right now, but the
// volume resource is using resource.RetryContext with the appropriate
// logic.
func volumeLookupReallyHard(client *Client, volPoolName string, key string) (*libvirt.StorageVol, error) {
virConn := client.libvirt
if virConn == nil {
return nil, fmt.Errorf(LibVirtConIsNil)
}
volume, err := virConn.StorageVolLookupByKey(key)
if err != nil {
virErr := err.(libvirt.Error)
if virErr.Code != uint32(libvirt.ErrNoStorageVol) {
return nil, fmt.Errorf("can't retrieve volume %s", key)
}
log.Printf("[INFO] Volume %s not found, attempting to start its pool", key)
volPool, err := virConn.StoragePoolLookupByName(volPoolName)
if err != nil {
return nil, fmt.Errorf("error retrieving pool %s for volume %s: %w", volPoolName, key, err)
}
active, err := virConn.StoragePoolIsActive(volPool)
if err != nil {
return nil, fmt.Errorf("error retrieving status of pool %s for volume %s: %w", volPoolName, key, err)
}
if active == 1 {
log.Printf("can't retrieve volume %s (and pool is active)", key)
return nil, nil
}
err = virConn.StoragePoolCreate(volPool, 0)
if err != nil {
return nil, fmt.Errorf("error starting pool %s: %w", volPoolName, err)
}
// attempt a new lookup
volume, err = virConn.StorageVolLookupByKey(key)
if err != nil {
virErr := err.(libvirt.Error)
if virErr.Code != uint32(libvirt.ErrNoStorageVol) {
return nil, fmt.Errorf("can't retrieve volume %s", key)
}
// does not exist, but no error
return nil, nil
}
}
return &volume, nil
}

View File

@ -38,11 +38,11 @@ func newDefVolumeFromXML(s string) (libvirtxml.StorageVolume, error) {
func newDefVolumeFromLibvirt(virConn *libvirt.Libvirt, volume libvirt.StorageVol) (libvirtxml.StorageVolume, error) {
volumeDefXML, err := virConn.StorageVolGetXMLDesc(volume, 0)
if err != nil {
return libvirtxml.StorageVolume{}, fmt.Errorf("could not get XML description for volume %s: %s", volume.Name, err)
return libvirtxml.StorageVolume{}, fmt.Errorf("could not get XML description for volume %s: %w", volume.Name, err)
}
volumeDef, err := newDefVolumeFromXML(volumeDefXML)
if err != nil {
return libvirtxml.StorageVolume{}, fmt.Errorf("could not get a volume definition from XML for %s: %s", volumeDef.Name, err)
return libvirtxml.StorageVolume{}, fmt.Errorf("could not get a volume definition from XML for %s: %w", volumeDef.Name, err)
}
return volumeDef, nil
}
@ -50,11 +50,11 @@ func newDefVolumeFromLibvirt(virConn *libvirt.Libvirt, volume libvirt.StorageVol
func newDefBackingStoreFromLibvirt(virConn *libvirt.Libvirt, baseVolume libvirt.StorageVol) (libvirtxml.StorageVolumeBackingStore, error) {
baseVolumeDef, err := newDefVolumeFromLibvirt(virConn, baseVolume)
if err != nil {
return libvirtxml.StorageVolumeBackingStore{}, fmt.Errorf("could not get volume: %s", err)
return libvirtxml.StorageVolumeBackingStore{}, fmt.Errorf("could not get volume: %w", err)
}
baseVolPath, err := virConn.StorageVolGetPath(baseVolume)
if err != nil {
return libvirtxml.StorageVolumeBackingStore{}, fmt.Errorf("could not get base image path: %s", err)
return libvirtxml.StorageVolumeBackingStore{}, fmt.Errorf("could not get base image path: %w", err)
}
var backingStoreVolFormat *libvirtxml.StorageVolumeTargetFormat
if baseVolumeDef.Target.Format != nil {

View File

@ -49,7 +49,7 @@ func (i *localImage) IsQCOW2() (bool, error) {
file, err := os.Open(i.path)
defer file.Close()
if err != nil {
return false, fmt.Errorf("error while opening %s: %s", i.path, err)
return false, fmt.Errorf("error while opening %s: %w", i.path, err)
}
buf := make([]byte, 8)
_, err = io.ReadAtLeast(file, buf, 8)
@ -63,7 +63,7 @@ func (i *localImage) Import(copier func(io.Reader) error, vol libvirtxml.Storage
file, err := os.Open(i.path)
defer file.Close()
if err != nil {
return fmt.Errorf("error while opening %s: %s", i.path, err)
return fmt.Errorf("error while opening %s: %w", i.path, err)
}
fi, err := file.Stat()
@ -114,7 +114,7 @@ func (i *httpImage) Size() (uint64, error) {
length, err := strconv.Atoi(response.Header.Get("Content-Length"))
if err != nil {
err = fmt.Errorf(
"error while getting Content-Length of \"%s\": %s - got %s",
"error while getting Content-Length of \"%s\": %w - got %s",
i.url.String(),
err,
response.Header.Get("Content-Length"))
@ -123,6 +123,7 @@ func (i *httpImage) Size() (uint64, error) {
return uint64(length), nil
}
//nolint:mnd
func (i *httpImage) IsQCOW2() (bool, error) {
client := &http.Client{}
req, _ := http.NewRequest("GET", i.url.String(), nil)
@ -167,7 +168,7 @@ func (i *httpImage) Import(copier func(io.Reader) error, vol libvirtxml.StorageV
if err != nil {
log.Printf("[DEBUG:] Error creating new request for source url %s: %s", i.url.String(), err)
return fmt.Errorf("error while downloading %s: %s", i.url.String(), err)
return fmt.Errorf("error while downloading %s: %w", i.url.String(), err)
}
if vol.Target.Timestamps != nil && vol.Target.Timestamps.Mtime != "" {
@ -178,7 +179,7 @@ func (i *httpImage) Import(copier func(io.Reader) error, vol libvirtxml.StorageV
for retryCount := 0; retryCount < maxHTTPRetries; retryCount++ {
response, err = client.Do(req)
if err != nil {
return fmt.Errorf("error while downloading %s: %v", i.url.String(), err)
return fmt.Errorf("error while downloading %s: %w", i.url.String(), err)
}
defer response.Body.Close()
@ -202,7 +203,7 @@ func (i *httpImage) Import(copier func(io.Reader) error, vol libvirtxml.StorageV
func newImage(source string) (image, error) {
url, err := url.Parse(source)
if err != nil {
return nil, fmt.Errorf("can't parse source '%s' as url: %s", source, err)
return nil, fmt.Errorf("can't parse source '%s' as url: %w", source, err)
}
if strings.HasPrefix(url.Scheme, "http") {
@ -226,6 +227,7 @@ func newImage(source string) (image, error) {
}
// isQCOW2Header returns True when the buffer starts with the qcow2 header.
//nolint:mnd
func isQCOW2Header(buf []byte) (bool, error) {
if len(buf) < 8 {
return false, fmt.Errorf("expected header of 8 bytes. Got %d", len(buf))

View File

@ -4,7 +4,6 @@ import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
@ -96,7 +95,7 @@ func TestNewImage(t *testing.T) {
func TestLocalImageDownload(t *testing.T) {
content := []byte("this is a qcow image... well, it is not")
tmpfile, err := ioutil.TempFile(t.TempDir(), "test-image-")
tmpfile, err := os.CreateTemp(t.TempDir(), "test-image-")
if err != nil {
t.Fatal(err)
}
@ -159,7 +158,7 @@ func TestRemoteImageDownloadRetry(t *testing.T) {
}
copier := func(r io.Reader) error {
_, err := ioutil.ReadAll(r)
_, err := io.ReadAll(r)
return err
}