lint cleanups
This commit is contained in:
parent
4a99136330
commit
01e507d95b
libvirt
cloudinit_def.gocoreos_ignition_def.godisk_def.godomain.godomain_def.gohelpers_test.gonetwork.gonetwork_def.gonetwork_dns.gonetwork_routes.gopool.goresource_libvirt_cloud_init.goresource_libvirt_cloud_init_test.goresource_libvirt_coreos_ignition_test.goresource_libvirt_domain.goresource_libvirt_domain_test.goresource_libvirt_network.goresource_libvirt_pool_test.goresource_libvirt_volume.goresource_libvirt_volume_test.gotimeout.go
uri
utils.goutils_domain_def.goutils_domain_def_test.goutils_net.goutils_net_test.goutils_volume.goutils_xslt.govolume.govolume_def.govolume_image.govolume_image_test.go
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ func resourceLibvirtVolume() *schema.Resource {
|
|||
},
|
||||
},
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: schema.ImportStatePassthrough,
|
||||
StateContext: schema.ImportStatePassthroughContext,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package libvirt
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
resourceStateTimeout = 1 * time.Minute
|
||||
resourceStateDelay = 5 * time.Second
|
||||
resourceStateMinTimeout = 3 * time.Second
|
||||
)
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue