dmacvicar / terraform-provider-libvirt

Terraform provider to provision infrastructure with Linux's KVM using libvirt
Apache License 2.0
1.54k stars 457 forks source link

Provider does not track active state of network #947

Open agorgl opened 2 years ago

agorgl commented 2 years ago

When creating a libvirt network without autostart and rebooting the hypervisor, the network and the instances (domains) are inactive / stopped, as expected.

Running terraform plan in this scenario we get this:

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # libvirt_domain.instance will be updated in-place
  ~ resource "libvirt_domain" "instance" {
        id          = "7dbfcef6-0dd3-4ee2-854e-0f31d3c30083"
        name        = "instance"
      ~ running     = false -> true
        # (10 unchanged attributes hidden)

        # (3 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Changes to Outputs:
  - instance_ip = "10.3.0.61" -> null

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

libvirt_domain.instance: Modifying... [id=7dbfcef6-0dd3-4ee2-854e-0f31d3c30083]
╷
│ Error: error creating libvirt domain: Requested operation is not valid: network 'network' is not active
│
│   with libvirt_domain.instance,
│   on main.tf line 80, in resource "libvirt_domain" "instance":
│   80: resource "libvirt_domain" "instance" {
│
╵

This shows that provider is able to track if the libvirt_domain is running and try to bring it up again, but it does NOT! track the state of the network it is connected to and we manually need to run virsh net-start network before running terraform plan again in order to get a successful result.

dmacvicar commented 1 year ago
// resourceLibvirtNetworkUpdate updates dynamically some attributes in the network
func resourceLibvirtNetworkUpdate(d *schema.ResourceData, meta interface{}) error {
    // 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)
    }

    network, err := virConn.NetworkLookupByUUID(parseUUID(d.Id()))
    if err != nil {
        return fmt.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)
    }

    active := activeInt == 1
    if !active {
        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)
        }
    }

in resourceLibvirtNetworkUpdate, which means resourceLibvirtNetworkUpdate is not called if the network is not update. Because we don't track the active property in resourceLibvirtNetworkRead.

But I am not sure what is the best way to track this. A computed attribute? Tell somehow terraform to foce the update even if no parameter from the schema is changed?