diff --git a/go.mod b/go.mod index b530faa417..6cff792c7d 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/clarketm/json v1.14.1 github.com/containers/image v3.0.2+incompatible github.com/coreos/ignition/v2 v2.3.0 - github.com/dmacvicar/terraform-provider-libvirt v0.6.2 + github.com/dmacvicar/terraform-provider-libvirt v0.6.4-0.20201216193629-2b60d7626ff8 github.com/fatih/color v1.10.0 // indirect github.com/frankban/quicktest v1.7.2 // indirect github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 diff --git a/go.sum b/go.sum index 949b49a063..f0f5305f76 100644 --- a/go.sum +++ b/go.sum @@ -374,6 +374,8 @@ github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TR github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dmacvicar/terraform-provider-libvirt v0.6.2 h1:jXhlKg24SNsG3EYWq45BbCocO5kNlTEOpZgpYLVhPYw= github.com/dmacvicar/terraform-provider-libvirt v0.6.2/go.mod h1:rUzijwUJHukJWZKi6PJXo9aJqGLXeUX6NDEy6O0UATg= +github.com/dmacvicar/terraform-provider-libvirt v0.6.4-0.20201216193629-2b60d7626ff8 h1:mTHVoBkXbLg/Yyi2BxT+N5y3v1/KjktwnEBls37g5Ds= +github.com/dmacvicar/terraform-provider-libvirt v0.6.4-0.20201216193629-2b60d7626ff8/go.mod h1:RZqLUAMFQ32TmKpk1Ayb4zeTe7+7k0jfsWpW1UTqVDw= github.com/dnaeon/go-vcr v0.0.0-20180920040454-5637cf3d8a31/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnaeon/go-vcr v1.0.1 h1:r8L/HqC0Hje5AXMu1ooW8oyQyOFv4GxqpL0nRP7SLLY= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/cloudinit_def.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/cloudinit_def.go index f4505e91eb..ad8d83a3aa 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/cloudinit_def.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/cloudinit_def.go @@ -11,9 +11,9 @@ import ( "path/filepath" "strings" + "github.com/google/uuid" "github.com/hooklift/iso9660" libvirt "github.com/libvirt/libvirt-go" - "github.com/mitchellh/packer/common/uuid" ) const userDataFileName string = "user-data" @@ -119,7 +119,7 @@ func (ci *defCloudInit) UploadIso(client *Client, iso string) (string, error) { // The ID is made by the volume ID (the internal one used by libvirt) // joined by the ";" with a UUID func (ci *defCloudInit) buildTerraformKey(volumeKey string) string { - return fmt.Sprintf("%s;%s", volumeKey, uuid.TimeOrderedUUID()) + return fmt.Sprintf("%s;%s", volumeKey, uuid.New()) } func getCloudInitVolumeKeyFromTerraformID(id string) (string, error) { diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/config.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/config.go index 493d29ae18..d560b1eb56 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/config.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/config.go @@ -4,6 +4,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/mutexkv" libvirt "github.com/libvirt/libvirt-go" "log" + "sync" ) // Config struct for the libvirt-provider @@ -15,6 +16,9 @@ type Config struct { type Client struct { libvirt *libvirt.Connect poolMutexKV *mutexkv.MutexKV + // define only one network at a time + // https://gitlab.com/libvirt/libvirt/-/issues/78 + networkMutex sync.Mutex } // Client libvirt, generate libvirt client given URI diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/coreos_ignition_def.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/coreos_ignition_def.go index 87ab399467..405ec1079e 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/coreos_ignition_def.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/coreos_ignition_def.go @@ -10,8 +10,8 @@ import ( "os" "strings" + "github.com/google/uuid" libvirt "github.com/libvirt/libvirt-go" - "github.com/mitchellh/packer/common/uuid" ) type defIgnition struct { @@ -104,7 +104,7 @@ func (ign *defIgnition) CreateAndUpload(client *Client) (string, error) { // The ID is made by the volume ID (the internal one used by libvirt) // joined by the ";" with a UUID func (ign *defIgnition) buildTerraformKey(volumeKey string) string { - return fmt.Sprintf("%s;%s", volumeKey, uuid.TimeOrderedUUID()) + return fmt.Sprintf("%s;%s", volumeKey, uuid.New()) } func getIgnitionVolumeKeyFromTerraformID(id string) (string, error) { diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/data_source_libvirt_network.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/data_source_libvirt_network.go index d3cff40f05..e696249eb1 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/data_source_libvirt_network.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/data_source_libvirt_network.go @@ -156,3 +156,58 @@ func resourceLibvirtNetworkDNSSRVRead(d *schema.ResourceData, meta interface{}) return nil } + +// a libvirt network dnsmasq template datasource +// +// Datasource example: +// +// data "libvirt_network_dnsmasq_options_template" "options" { +// count = length(var.libvirt_dnsmasq_options) +// option_name = keys(var.libvirt_dnsmasq_options)[count.index] +// option_value = values(var.libvirt_dnsmasq_options)[count.index] +// } +// +// resource "libvirt_network" "k8snet" { +// ... +// dnsmasq_options = [{ +// options = [ "${flatten(data.libvirt_network_dnsmasq_options_template.options.*.rendered)}" ] +// }] +// ... +// } +// +func datasourceLibvirtNetworkDnsmasqOptionsTemplate() *schema.Resource { + return &schema.Resource{ + Read: resourceLibvirtNetworkDnsmasqOptionsRead, + Schema: map[string]*schema.Schema{ + "option_name": { + Type: schema.TypeString, + Required: true, + }, + "option_value": { + Type: schema.TypeString, + Required: true, + }, + "rendered": { + Type: schema.TypeMap, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Computed: true, + }, + }, + } +} + +func resourceLibvirtNetworkDnsmasqOptionsRead(d *schema.ResourceData, meta interface{}) error { + dnsmasqOption := map[string]interface{}{} + if name, ok := d.GetOk("option_name"); ok { + dnsmasqOption["option_name"] = name.(string) + } + if value, ok := d.GetOk("option_value"); ok { + dnsmasqOption["option_value"] = value.(string) + } + d.Set("rendered", dnsmasqOption) + d.SetId(strconv.Itoa(hashcode.String(fmt.Sprintf("%v", dnsmasqOption)))) + + return nil +} diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain.go index cb309d0d7a..a6bdcf8ffc 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain.go @@ -18,12 +18,6 @@ import ( "github.com/libvirt/libvirt-go-xml" ) -// deprecated, now defaults to not use it, but we warn the user -const skipQemuAgentEnvVar = "TF_SKIP_QEMU_AGENT" - -// if explicitly enabled -const useQemuAgentEnvVar = "TF_USE_QEMU_AGENT" - const domWaitLeaseStillWaiting = "waiting-addresses" const domWaitLeaseDone = "all-addresses-obtained" @@ -305,8 +299,8 @@ func setVideo(d *schema.ResourceData, domainDef *libvirtxml.Domain) error { } func setGraphics(d *schema.ResourceData, domainDef *libvirtxml.Domain, arch string) error { - // For s390x, ppc64 and ppc64le spice is not supported - if arch == "s390x" || strings.HasPrefix(arch, "ppc64") { + // For aarch64, s390x, ppc64 and ppc64le spice is not supported + if arch == "aarch64" || arch == "s390x" || strings.HasPrefix(arch, "ppc64") { domainDef.Devices.Graphics = nil return nil } @@ -451,7 +445,13 @@ func setConsoles(d *schema.ResourceData, domainDef *libvirtxml.Domain) { Type: "telnet", } case "pty": - fallthrough + if sourcePath, ok := d.GetOk(prefix + ".source_path"); ok { + console.Source = &libvirtxml.DomainChardevSource{ + Pty: &libvirtxml.DomainChardevSourcePty{ + Path: sourcePath.(string), + }, + } + } default: if sourcePath, ok := d.GetOk(prefix + ".source_path"); ok { console.Source = &libvirtxml.DomainChardevSource{ diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain_def.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain_def.go index f68b7abd19..46bc25b595 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain_def.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/domain_def.go @@ -62,6 +62,9 @@ func newDomainDef() libvirtxml.Domain { }, Channels: []libvirtxml.DomainChannel{ { + Source: &libvirtxml.DomainChardevSource{ + UNIX: &libvirtxml.DomainChardevSourceUNIX{}, + }, Target: &libvirtxml.DomainChannelTarget{ VirtIO: &libvirtxml.DomainChannelTargetVirtIO{ Name: "org.qemu.guest_agent.0", @@ -114,6 +117,12 @@ func newDomainDefForConnection(virConn *libvirt.Connect, rd *schema.ResourceData d.OS.Type.Arch = arch } + if d.OS.Type.Arch == "aarch64" { + // for aarch64 speciffying this will automatically select the firmware and NVRAM file + // reference: https://libvirt.org/formatdomain.html#bios-bootloader + d.OS.Firmware = "efi" + } + caps, err := getHostCapabilities(virConn) if err != nil { return d, err diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/helper/suppress/strings.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/helper/suppress/strings.go index 5b6af03b68..ab4df485e5 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/helper/suppress/strings.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/helper/suppress/strings.go @@ -1,8 +1,8 @@ package suppress import ( - "strings" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "strings" ) func CaseDifference(_, old, new string, _ *schema.ResourceData) bool { diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/network.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/network.go index 13040bf682..21a77d6ff2 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/network.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/network.go @@ -9,7 +9,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/libvirt/libvirt-go" - "github.com/libvirt/libvirt-go-xml" + libvirtxml "github.com/libvirt/libvirt-go-xml" ) func waitForNetworkActive(network libvirt.Network) resource.StateRefreshFunc { @@ -174,3 +174,23 @@ func getMTUFromResource(d *schema.ResourceData) *libvirtxml.NetworkMTU { return nil } + +// getDNSMasqOptionFromResource returns a list of dnsmasq options +// from the network definition +func getDNSMasqOptionFromResource(d *schema.ResourceData) ([]libvirtxml.NetworkDnsmasqOption, error) { + var dnsmasqOption []libvirtxml.NetworkDnsmasqOption + dnsmasqOptionPrefix := "dnsmasq_options.0" + if dnsmasqOptionCount, ok := d.GetOk(dnsmasqOptionPrefix + ".options.#"); ok { + for i := 0; i < dnsmasqOptionCount.(int); i++ { + dnsmasqOptionsPrefix := fmt.Sprintf(dnsmasqOptionPrefix+".options.%d", i) + + optionName := d.Get(dnsmasqOptionsPrefix + ".option_name").(string) + optionValue := d.Get(dnsmasqOptionsPrefix + ".option_value").(string) + dnsmasqOption = append(dnsmasqOption, libvirtxml.NetworkDnsmasqOption{ + Value: optionName + "=" + optionValue, + }) + } + } + + return dnsmasqOption, nil +} diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/network_def.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/network_def.go index 91920582c4..d46ffbb023 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/network_def.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/network_def.go @@ -4,6 +4,7 @@ import ( "encoding/xml" "fmt" "log" + "net" libvirt "github.com/libvirt/libvirt-go" "github.com/libvirt/libvirt-go-xml" @@ -15,6 +16,9 @@ func HasDHCP(net libvirtxml.Network) bool { if net.Forward.Mode == "nat" || net.Forward.Mode == "route" || net.Forward.Mode == "" { return true } + } else { + // isolated network + return true } return false } @@ -78,24 +82,60 @@ func getHostXMLDesc(ip, mac, name string) string { } // Adds a new static host to the network -func addHost(n *libvirt.Network, ip, mac, name string) error { +func addHost(n *libvirt.Network, ip, mac, name string, xmlIdx int) error { xmlDesc := getHostXMLDesc(ip, mac, name) log.Printf("Adding host with XML:\n%s", xmlDesc) - return n.Update(libvirt.NETWORK_UPDATE_COMMAND_ADD_LAST, libvirt.NETWORK_SECTION_IP_DHCP_HOST, -1, xmlDesc, libvirt.NETWORK_UPDATE_AFFECT_CURRENT) + // From https://libvirt.org/html/libvirt-libvirt-network.html#virNetworkUpdateFlags + // Update live and config for hosts to make update permanent across reboots + return n.Update(libvirt.NETWORK_UPDATE_COMMAND_ADD_LAST, libvirt.NETWORK_SECTION_IP_DHCP_HOST, xmlIdx, xmlDesc, libvirt.NETWORK_UPDATE_AFFECT_CONFIG|libvirt.NETWORK_UPDATE_AFFECT_LIVE) } // Update a static host from the network -func updateHost(n *libvirt.Network, ip, mac, name string) error { +func updateHost(n *libvirt.Network, ip, mac, name string, xmlIdx int) error { xmlDesc := getHostXMLDesc(ip, mac, name) log.Printf("Updating host with XML:\n%s", xmlDesc) - return n.Update(libvirt.NETWORK_UPDATE_COMMAND_MODIFY, libvirt.NETWORK_SECTION_IP_DHCP_HOST, -1, xmlDesc, libvirt.NETWORK_UPDATE_AFFECT_CURRENT) + // From https://libvirt.org/html/libvirt-libvirt-network.html#virNetworkUpdateFlags + // Update live and config for hosts to make update permanent across reboots + return n.Update(libvirt.NETWORK_UPDATE_COMMAND_MODIFY, libvirt.NETWORK_SECTION_IP_DHCP_HOST, xmlIdx, xmlDesc, libvirt.NETWORK_UPDATE_AFFECT_CONFIG|libvirt.NETWORK_UPDATE_AFFECT_LIVE) +} + +// Get the network index of the target network +func getNetworkIdx(n *libvirtxml.Network, ip string) (int, error) { + xmlIdx := -1 + + if n == nil { + return xmlIdx, fmt.Errorf("failed to convert to libvirt XML") + } + + for idx, netIps := range n.IPs { + _, netw, err := net.ParseCIDR(fmt.Sprintf("%s/%d", netIps.Address, netIps.Prefix)) + if err != nil { + return xmlIdx, err + } + + if netw.Contains(net.ParseIP(ip)) { + xmlIdx = idx + break + } + } + + return xmlIdx, nil } // Tries to update first, if that fails, it will add it func updateOrAddHost(n *libvirt.Network, ip, mac, name string) error { - err := updateHost(n, ip, mac, name) + xmlNet, _ := getXMLNetworkDefFromLibvirt(n) + // We don't check the error above + // if we can't parse the network to xml for some kind fo reasons + // we will return the default '-1' value. + xmlIdx, err := getNetworkIdx(&xmlNet, ip) + if err == nil { + log.Printf("Error during detecting network index: %s\nUsing default value: %d", err, xmlIdx) + } + + err = updateHost(n, ip, mac, name, xmlIdx) if virErr, ok := err.(libvirt.Error); ok && virErr.Code == libvirt.ERR_OPERATION_INVALID && virErr.Domain == libvirt.FROM_NETWORK { - return addHost(n, ip, mac, name) + return addHost(n, ip, mac, name, xmlIdx) } return err } diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/provider.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/provider.go index 9ddaab89ef..3bb4ce9270 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/provider.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/provider.go @@ -29,8 +29,9 @@ func Provider() terraform.ResourceProvider { }, DataSourcesMap: map[string]*schema.Resource{ - "libvirt_network_dns_host_template": datasourceLibvirtNetworkDNSHostTemplate(), - "libvirt_network_dns_srv_template": datasourceLibvirtNetworkDNSSRVTemplate(), + "libvirt_network_dns_host_template": datasourceLibvirtNetworkDNSHostTemplate(), + "libvirt_network_dns_srv_template": datasourceLibvirtNetworkDNSSRVTemplate(), + "libvirt_network_dnsmasq_options_template": datasourceLibvirtNetworkDnsmasqOptionsTemplate(), }, ConfigureFunc: providerConfigure, diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/qemu_agent.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/qemu_agent.go index 71dfc34c9e..2d2ce06ab1 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/qemu_agent.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/qemu_agent.go @@ -113,9 +113,9 @@ func qemuAgentGetInterfacesInfo(domain Domain, wait4ipv4 bool) []libvirt.DomainI Pending: []string{qemuGetIfaceWait}, Target: []string{qemuGetIfaceDone}, Refresh: qemuAgentInterfacesRefreshFunc(domain, wait4ipv4), - MinTimeout: 4 * time.Second, - Delay: 4 * time.Second, // Wait this time before starting checks - Timeout: 30 * time.Second, + MinTimeout: 1 * time.Minute, + Delay: 30 * time.Second, // Wait this time before starting checks + Timeout: 5 * time.Minute, } interfaces, err := qemuAgentQuery.WaitForState() diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_network.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_network.go index 4766c2fe0b..ba88783b43 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_network.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/resource_libvirt_network.go @@ -10,7 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/libvirt/libvirt-go" - "github.com/libvirt/libvirt-go-xml" + libvirtxml "github.com/libvirt/libvirt-go-xml" ) const ( @@ -35,6 +35,9 @@ const ( // "addresses" can contain (0 or 1) ipv4 and (0 or 1) ipv6 subnets // "mode" can be one of: "nat" (default), "isolated" // +// Not all resources support update, for those that require ForceNew +// 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, @@ -54,7 +57,8 @@ func resourceLibvirtNetwork() *schema.Resource { "domain": { Type: schema.TypeString, Optional: true, - ForceNew: false, + // libvirt cannot update it so force new + ForceNew: true, }, "mode": { // can be "none", "nat" (default), "route", "bridge" Type: schema.TypeString, @@ -235,6 +239,38 @@ func resourceLibvirtNetwork() *schema.Resource { }, }, }, + "dnsmasq_options": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "options": { + Type: schema.TypeList, + Optional: true, + ForceNew: false, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "option_name": { + Type: schema.TypeString, + // This should be required, but Terraform does validation too early + // and therefore doesn't recognize that this is set when assigning from + // a rendered dnsmasq_options template. + Optional: true, + }, + "option_value": { + Type: schema.TypeString, + // This should be required, but Terraform does validation too early + // and therefore doesn't recognize that this is set when assigning from + // a rendered dnsmasq_options template. + Optional: true, + }, + }, + }, + }, + }, + }, + }, "xml": { Type: schema.TypeList, Optional: true, @@ -339,25 +375,6 @@ func resourceLibvirtNetworkUpdate(d *schema.ResourceData, meta interface{}) erro d.SetPartial("bridge") } - // detect changes in the domain - if d.HasChange("domain") { - networkDomain := getDomainFromResource(d) - - data, err := xmlMarshallIndented(networkDomain) - if err != nil { - return fmt.Errorf("serialize update: %s", err) - } - - log.Printf("[DEBUG] Updating domain for libvirt network '%s' with XML: %s", networkName, data) - err = network.Update(libvirt.NETWORK_UPDATE_COMMAND_MODIFY, libvirt.NETWORK_SECTION_DOMAIN, -1, - data, libvirt.NETWORK_UPDATE_AFFECT_LIVE|libvirt.NETWORK_UPDATE_AFFECT_CONFIG) - if err != nil { - return fmt.Errorf("Error when updating domain in %s: %s", networkName, err) - } - - d.SetPartial("domain") - } - d.Partial(false) return nil } @@ -437,6 +454,15 @@ func resourceLibvirtNetworkCreate(d *schema.ResourceData, meta interface{}) erro return fmt.Errorf("unsupported network mode '%s'", networkDef.Forward.Mode) } + dnsmasqOption, err := getDNSMasqOptionFromResource(d) + if err != nil { + return err + } + dnsMasqOptions := libvirtxml.NetworkDnsmasqOptions{ + Option: dnsmasqOption, + } + networkDef.DnsmasqOptions = &dnsMasqOptions + // parse any static routes routes, err := getRoutesFromResource(d) if err != nil { @@ -462,14 +488,29 @@ func resourceLibvirtNetworkCreate(d *schema.ResourceData, meta interface{}) erro return fmt.Errorf("Error applying XSLT stylesheet: %s", err) } - log.Printf("[DEBUG] Creating libvirt network at %s: %s", connectURI, data) - network, err := virConn.NetworkDefineXML(data) + network, err := func() (*libvirt.Network, error) { + // define only one network at a time + // see https://gitlab.com/libvirt/libvirt/-/issues/78 + meta.(*Client).networkMutex.Lock() + defer meta.(*Client).networkMutex.Unlock() + + log.Printf("[DEBUG] Creating libvirt network at %s: %s", connectURI, data) + return virConn.NetworkDefineXML(data) + }() + if err != nil { return fmt.Errorf("Error defining libvirt network: %s - %s", err, data) } + err = network.Create() if err != nil { - return fmt.Errorf("Error clearing libvirt network: %s", err) + // in some cases, the network creation fails but an artifact is created + // an 'broken network". Remove the network in case of failure + // see https://github.com/dmacvicar/terraform-provider-libvirt/issues/739 + // don't handle the error for destroying + network.Destroy() + network.Undefine() + return fmt.Errorf("Error creating libvirt network: %s", err) } defer network.Free() @@ -633,22 +674,24 @@ func resourceLibvirtNetworkDelete(d *schema.ResourceData, meta interface{}) erro if err != nil { return fmt.Errorf("Couldn't determine if network is active: %s", err) } + // network can be in 2 states, handles this case by case + + // in case network is inactive just undefine it if !active { - // we have to restart an inactive network, otherwise it won't be - // possible to remove it. - if err := network.Create(); err != nil { - return fmt.Errorf("Cannot restart an inactive network %s", err) + if err := network.Undefine(); err != nil { + return fmt.Errorf("Couldn't undefine libvirt network: %s", err) } } + // network is active, so we need to destroy it and undefine it + if active { + if err := network.Destroy(); err != nil { + return fmt.Errorf("When destroying libvirt network: %s", err) + } - if err := network.Destroy(); err != nil { - return fmt.Errorf("When destroying libvirt network: %s", err) + if err := network.Undefine(); err != nil { + return fmt.Errorf("Couldn't undefine libvirt network: %s", err) + } } - - if err := network.Undefine(); err != nil { - return fmt.Errorf("Couldn't undefine libvirt network: %s", err) - } - stateConf := &resource.StateChangeConf{ Pending: []string{"ACTIVE"}, Target: []string{"NOT-EXISTS"}, diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/utils_domain_def.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/utils_domain_def.go index ab56fc1f5c..cc2ff575fb 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/utils_domain_def.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/utils_domain_def.go @@ -21,20 +21,39 @@ func getGuestForArchType(caps libvirtxml.Caps, arch string, virttype string) (li return libvirtxml.CapsGuest{}, fmt.Errorf("[DEBUG] Could not find any guests for architecure type %s/%s", virttype, arch) } +func lookupMachine(machines []libvirtxml.CapsGuestMachine, targetmachine string) string { + for _, machine := range machines { + if machine.Name == targetmachine { + if machine.Canonical != "" { + return machine.Canonical + } + return machine.Name + } + } + return "" +} + func getCanonicalMachineName(caps libvirtxml.Caps, arch string, virttype string, targetmachine string) (string, error) { guest, err := getGuestForArchType(caps, arch, virttype) if err != nil { return "", err } - for _, machine := range guest.Arch.Machines { - if machine.Name == targetmachine { - if machine.Canonical != "" { - return machine.Canonical, nil - } - return machine.Name, nil + /* Machine entries can be in the guest.Arch.Machines level as well as + under each guest.Arch.Domains[].Machines */ + + name := lookupMachine(guest.Arch.Machines, targetmachine) + if name != "" { + return name, nil + } + + for _, domain := range guest.Arch.Domains { + name := lookupMachine(domain.Machines, targetmachine) + if name != "" { + return name, nil } } + return "", fmt.Errorf("[WARN] Cannot find machine type %s for %s/%s in %v", targetmachine, virttype, arch, caps) } diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/utils_net.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/utils_net.go index cc67d0c70f..f83f2d0a84 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/utils_net.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/utils_net.go @@ -48,29 +48,38 @@ func randomPort() int { return rand.Intn(maxPort-minPort) + minPort } -// freeNetworkInterface returns a free network interface -func freeNetworkInterface(basename string) (string, error) { - for i := 0; i < maxIfaceNum; i++ { - ifaceName := fmt.Sprintf("%s%d", basename, i) - _, err := net.InterfaceByName(ifaceName) - if err != nil { - return ifaceName, nil +func getNetMaskWithMax16Bits(m net.IPMask) net.IPMask { + ones, bits := m.Size() + + if bits-ones > 16 { + if bits == 128 { + // IPv6 Mask with max 16 bits + return net.CIDRMask(128-16, 128) } + + // IPv4 Mask with max 16 bits + return net.CIDRMask(32-16, 32) } - return "", fmt.Errorf("could not obtain a free network interface") + + return m } // networkRange calculates the first and last IP addresses in an IPNet func networkRange(network *net.IPNet) (net.IP, net.IP) { netIP := network.IP.To4() - lastIP := net.IPv4(0, 0, 0, 0).To4() + lastIP := net.IPv4zero.To4() if netIP == nil { netIP = network.IP.To16() lastIP = net.IPv6zero.To16() } firstIP := netIP.Mask(network.Mask) + // intermediate network mask with max 16 bits for hosts + // We need a mask with max 16 bits since libvirt only supports 65535) IP's per subnet + // 2^16 = 65536 (minus broadcast and .1) + intMask := getNetMaskWithMax16Bits(network.Mask) + for i := 0; i < len(lastIP); i++ { - lastIP[i] = netIP[i] | ^network.Mask[i] + lastIP[i] = netIP[i] | ^intMask[i] } return firstIP, lastIP } @@ -96,7 +105,7 @@ func (fws *fileWebServer) Start() error { handler := http.NewServeMux() handler.Handle("/", http.FileServer(http.Dir(dir))) - fws.server = &http.Server{Addr: fmt.Sprintf(":%d", fws.Port), Handler: handler} + fws.server = &http.Server{Addr: fmt.Sprintf("127.0.0.1:%d", fws.Port), Handler: handler} ln, err := net.Listen("tcp", fws.server.Addr) if err != nil { return err diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/utils_xslt.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/utils_xslt.go index 6b7aa58220..27614ab5b3 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/utils_xslt.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/utils_xslt.go @@ -89,6 +89,7 @@ func transformXML(xml string, xslt string) (string, error) { xmlFile.Name()) transformedXML, err := cmd.Output() if err != nil { + log.Printf("[ERROR] Failed to run xsltproc (is it installed?)") return xml, err } log.Printf("[DEBUG] Transformed XML with user specified XSLT:\n%s", transformedXML) diff --git a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/volume.go b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/volume.go index b0bf0c5750..eb48a2f653 100644 --- a/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/volume.go +++ b/vendor/github.com/dmacvicar/terraform-provider-libvirt/libvirt/volume.go @@ -68,7 +68,12 @@ func volumeWaitDeleted(virConn *libvirt.Connect, key string) error { func volumeDelete(client *Client, key string) error { volume, err := client.libvirt.LookupStorageVolByKey(key) if err != nil { - return fmt.Errorf("Can't retrieve volume %s: %v", key, err) + virErr := err.(libvirt.Error) + if virErr.Code != libvirt.ERR_NO_STORAGE_VOL { + return fmt.Errorf("volumeDelete: Can't retrieve volume %s: %v", key, err) + } + // Volume already deleted. + return nil } defer volume.Free() diff --git a/vendor/github.com/mitchellh/packer/LICENSE b/vendor/github.com/mitchellh/packer/LICENSE deleted file mode 100644 index a612ad9813..0000000000 --- a/vendor/github.com/mitchellh/packer/LICENSE +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/vendor/github.com/mitchellh/packer/common/uuid/uuid.go b/vendor/github.com/mitchellh/packer/common/uuid/uuid.go deleted file mode 100644 index d8b9830be2..0000000000 --- a/vendor/github.com/mitchellh/packer/common/uuid/uuid.go +++ /dev/null @@ -1,24 +0,0 @@ -package uuid - -import ( - "crypto/rand" - "fmt" - "time" -) - -// Generates a time ordered UUID. Top 32 bits are a timestamp, -// bottom 96 are random. -func TimeOrderedUUID() string { - unix := uint32(time.Now().UTC().Unix()) - - b := make([]byte, 12) - n, err := rand.Read(b) - if n != len(b) { - err = fmt.Errorf("Not enough entropy available") - } - if err != nil { - panic(err) - } - return fmt.Sprintf("%08x-%04x-%04x-%04x-%04x%08x", - unix, b[0:2], b[2:4], b[4:6], b[6:8], b[8:]) -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 38121d2714..b781a5493c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -441,7 +441,7 @@ github.com/davecgh/go-spew/spew github.com/dgrijalva/jwt-go # github.com/dimchansky/utfbom v1.1.0 github.com/dimchansky/utfbom -# github.com/dmacvicar/terraform-provider-libvirt v0.6.2 +# github.com/dmacvicar/terraform-provider-libvirt v0.6.4-0.20201216193629-2b60d7626ff8 ## explicit github.com/dmacvicar/terraform-provider-libvirt/libvirt github.com/dmacvicar/terraform-provider-libvirt/libvirt/helper/suppress @@ -1035,8 +1035,6 @@ github.com/mitchellh/go-wordwrap github.com/mitchellh/hashstructure # github.com/mitchellh/mapstructure v1.3.3 github.com/mitchellh/mapstructure -# github.com/mitchellh/packer v1.3.2 -github.com/mitchellh/packer/common/uuid # github.com/mitchellh/panicwrap v1.0.0 github.com/mitchellh/panicwrap # github.com/mitchellh/reflectwalk v1.0.1