diff --git a/opennebula/helpers_vr.go b/opennebula/helpers_vr.go index bea7378d6..fdb1b970b 100644 --- a/opennebula/helpers_vr.go +++ b/opennebula/helpers_vr.go @@ -101,6 +101,13 @@ func vrNICAttach(ctx context.Context, timeout time.Duration, controller *goca.Co updatedNICsLoop: for i, nic := range updatedNICs { + // For VRouter NICs, floating IPs are set using the "IP" field, but it is represented in the ON API + // as the "VROUTER_IP" field. + if vrouterIP, err := nic.GetStr("VROUTER_IP"); err == nil { + if _, err = nic.GetStr("IP"); err != nil { + nic.Add("IP", vrouterIP) + } + } for _, pair := range nicTpl.Pairs { value, err := nic.GetStr(pair.Key()) diff --git a/opennebula/resource_opennebula_virtual_network.go b/opennebula/resource_opennebula_virtual_network.go index 309b588e1..05024bed8 100644 --- a/opennebula/resource_opennebula_virtual_network.go +++ b/opennebula/resource_opennebula_virtual_network.go @@ -1694,15 +1694,16 @@ func resourceOpennebulaVirtualNetworkDelete(ctx context.Context, d *schema.Resou } log.Printf("[INFO] Successfully released reservered IP addresses.") - err = vnc.Delete() - if err != nil { - diags = append(diags, diag.Diagnostic{ - Severity: diag.Error, - Summary: "Failed to delete", - Detail: fmt.Sprintf("virtual network (ID: %s): %s", d.Id(), err), - }) - return diags - } + err = resource.RetryContext(ctx, d.Timeout(schema.TimeoutDelete), func() *resource.RetryError { + err = vnc.Delete() + if err != nil { + if strings.Contains(err.Error(), "Can not remove a virtual network with leases in use") { + return resource.RetryableError(err) + } + return resource.NonRetryableError(err) + } + return nil + }) timeout := d.Timeout(schema.TimeoutDelete) transient := []string{vn.Init.String(), vn.Ready.String()} @@ -1716,7 +1717,7 @@ func resourceOpennebulaVirtualNetworkDelete(ctx context.Context, d *schema.Resou return diags } - log.Printf("[INFO] Successfully deleted Vnet\n") + log.Printf("[INFO] Successfully deleted Vnet (ID: %s)\n", d.Id()) return nil } diff --git a/opennebula/resource_opennebula_virtual_router_nic.go b/opennebula/resource_opennebula_virtual_router_nic.go index c00941715..17bdd1e0a 100644 --- a/opennebula/resource_opennebula_virtual_router_nic.go +++ b/opennebula/resource_opennebula_virtual_router_nic.go @@ -87,6 +87,12 @@ func resourceOpennebulaVirtualRouterNIC() *schema.Resource { Default: false, ForceNew: true, }, + "ip": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + }, }, } } @@ -137,6 +143,10 @@ func resourceOpennebulaVirtualRouterNICCreate(ctx context.Context, d *schema.Res } } + if v, ok := d.GetOk("ip"); ok { + nicTpl.Add("IP", v.(string)) + } + // wait before checking NIC nicID, err := vrNICAttach(ctx, d.Timeout(schema.TimeoutCreate), controller, vRouterID, nicTpl) if err != nil { @@ -209,6 +219,13 @@ func resourceOpennebulaVirtualRouterNICRead(ctx context.Context, d *schema.Resou floatingIP, _ := nic.GetStr("FLOATING_IP") floatingOnly, _ := nic.GetStr("FLOATING_ONLY") + ip, _ := nic.Get("IP") + + // For VRouter NICs, floating IPs are set using the "IP" field, but it is represented in the ON API + // as the "VROUTER_IP" field. + if strings.ToUpper(floatingIP) == "YES" { + ip, _ = nic.Get("VROUTER_IP") + } d.Set("network_id", networkID) d.Set("virtual_router_id", vr.ID) @@ -219,6 +236,7 @@ func resourceOpennebulaVirtualRouterNICRead(ctx context.Context, d *schema.Resou d.Set("security_groups", sg) d.Set("floating_ip", strings.ToUpper(floatingIP) == "YES") d.Set("floating_only", strings.ToUpper(floatingOnly) == "YES") + d.Set("ip", ip) return nil } diff --git a/opennebula/resource_opennebula_virtual_router_test.go b/opennebula/resource_opennebula_virtual_router_test.go index e59745847..31768017f 100644 --- a/opennebula/resource_opennebula_virtual_router_test.go +++ b/opennebula/resource_opennebula_virtual_router_test.go @@ -121,8 +121,10 @@ func TestAccVirtualRouter(t *testing.T) { resource.TestCheckResourceAttrSet("opennebula_virtual_router_nic.nic2", "network_id"), resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic1", "floating_ip", "true"), resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic1", "floating_only", "true"), + resource.TestCheckResourceAttrSet("opennebula_virtual_router_nic.nic1", "ip"), resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic2", "floating_ip", "false"), resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic2", "floating_only", "false"), + resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic2", "ip", ""), testAccCheckVirtualRouterPermissions(&shared.Permissions{ OwnerU: 1, OwnerM: 1, @@ -156,6 +158,75 @@ func TestAccVirtualRouter(t *testing.T) { }, "testacc-vr"), ), }, + { + Config: testAccVirtualRouterDeleteSecondVrouter, + Check: resource.ComposeTestCheckFunc( + // Virtual router + resource.TestCheckResourceAttr("opennebula_virtual_router.test", "name", "testacc-vr"), + resource.TestCheckResourceAttr("opennebula_virtual_router.test", "permissions", "642"), + resource.TestCheckResourceAttr("opennebula_virtual_router.test", "group", "oneadmin"), + resource.TestCheckResourceAttrSet("opennebula_virtual_router.test", "uid"), + resource.TestCheckResourceAttrSet("opennebula_virtual_router.test", "gid"), + resource.TestCheckResourceAttrSet("opennebula_virtual_router.test", "uname"), + resource.TestCheckResourceAttrSet("opennebula_virtual_router.test", "gname"), + testAccCheckVirtualRouterPermissions(&shared.Permissions{ + OwnerU: 1, + OwnerM: 1, + GroupU: 1, + OtherM: 1, + }, "testacc-vr"), + ), + }, + { + Config: testAccVirtualRouterAddNICsWithIPs, + Check: resource.ComposeTestCheckFunc( + // Virtual router + resource.TestCheckResourceAttr("opennebula_virtual_router.test", "name", "testacc-vr"), + resource.TestCheckResourceAttr("opennebula_virtual_router.test", "permissions", "642"), + resource.TestCheckResourceAttr("opennebula_virtual_router.test", "group", "oneadmin"), + resource.TestCheckResourceAttrSet("opennebula_virtual_router.test", "uid"), + resource.TestCheckResourceAttrSet("opennebula_virtual_router.test", "gid"), + resource.TestCheckResourceAttrSet("opennebula_virtual_router.test", "uname"), + resource.TestCheckResourceAttrSet("opennebula_virtual_router.test", "gname"), + resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic_floating_ip_specified", "floating_ip", "true"), + resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic_floating_ip_specified", "floating_only", "false"), + resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic_floating_ip_specified", "ip", "172.16.100.160"), + testAccCheckVirtualRouterPermissions(&shared.Permissions{ + OwnerU: 1, + OwnerM: 1, + GroupU: 1, + OtherM: 1, + }, "testacc-vr"), + ), + }, + { + Config: testAccVirtualRouterUpdateNICsWithIPs, + Check: resource.ComposeTestCheckFunc( + // Virtual router + resource.TestCheckResourceAttr("opennebula_virtual_router.test", "name", "testacc-vr"), + resource.TestCheckResourceAttr("opennebula_virtual_router.test", "permissions", "642"), + resource.TestCheckResourceAttr("opennebula_virtual_router.test", "group", "oneadmin"), + resource.TestCheckResourceAttrSet("opennebula_virtual_router.test", "uid"), + resource.TestCheckResourceAttrSet("opennebula_virtual_router.test", "gid"), + resource.TestCheckResourceAttrSet("opennebula_virtual_router.test", "uname"), + resource.TestCheckResourceAttrSet("opennebula_virtual_router.test", "gname"), + resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic_IP_specified", "floating_ip", "false"), + resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic_IP_specified", "floating_only", "false"), + resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic_IP_specified", "ip", "172.16.100.120"), + resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic_floating_only_IP_specified", "floating_ip", "true"), + resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic_floating_only_IP_specified", "floating_only", "true"), + resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic_floating_only_IP_specified", "ip", "172.16.100.121"), + resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic_floating_ip_specified", "floating_ip", "true"), + resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic_floating_ip_specified", "floating_only", "false"), + resource.TestCheckResourceAttr("opennebula_virtual_router_nic.nic_floating_ip_specified", "ip", "172.16.100.160"), + testAccCheckVirtualRouterPermissions(&shared.Permissions{ + OwnerU: 1, + OwnerM: 1, + GroupU: 1, + OtherM: 1, + }, "testacc-vr"), + ), + }, }, }) } @@ -246,12 +317,12 @@ func testAccCheckVirtualRouterPermissions(expected *shared.Permissions, resource var testAccVirtualRouterMachineTemplate = ` resource "opennebula_virtual_router_instance_template" "test" { - name = "testacc-vr-template" + name = "testacc-vr-template" permissions = "642" - group = "oneadmin" - cpu = "0.5" - vcpu = "1" - memory = "512" + group = "oneadmin" + cpu = "0.5" + vcpu = "1" + memory = "512" context = { dns_hostname = "yes" @@ -291,9 +362,9 @@ resource "opennebula_virtual_network" "network1" { group = "oneadmin" security_groups = [0] cluster_ids = [0] - } +} - resource "opennebula_virtual_network" "network2" { +resource "opennebula_virtual_network" "network2" { name = "test-net2" type = "bridge" bridge = "onebr" @@ -307,9 +378,9 @@ resource "opennebula_virtual_network" "network1" { group = "oneadmin" security_groups = [0] cluster_ids = [0] - } +} - resource "opennebula_virtual_network" "network3" { +resource "opennebula_virtual_network" "network3" { name = "test-net3" type = "bridge" bridge = "onebr" @@ -323,7 +394,7 @@ resource "opennebula_virtual_network" "network1" { group = "oneadmin" security_groups = [0] cluster_ids = [0] - } +} ` var testAccVirtualRouterConfigBasic = testAccVirtualRouterMachineTemplate + ` @@ -332,22 +403,22 @@ resource "opennebula_virtual_router_instance" "test" { name = "testacc-vr-virtual-machine" group = "oneadmin" permissions = "642" - memory = 128 - cpu = 0.1 + memory = 128 + cpu = 0.1 virtual_router_id = opennebula_virtual_router.test.id } resource "opennebula_virtual_router" "test" { - name = "testacc-vr" - permissions = "642" - group = "oneadmin" + name = "testacc-vr" + permissions = "642" + group = "oneadmin" - instance_template_id = opennebula_virtual_router_instance_template.test.id + instance_template_id = opennebula_virtual_router_instance_template.test.id - tags = { - customer = "1" - } + tags = { + customer = "1" + } } ` @@ -357,8 +428,8 @@ resource "opennebula_virtual_router_instance" "test" { name = "testacc-vr-virtual-machine" group = "oneadmin" permissions = "642" - memory = 128 - cpu = 0.1 + memory = 128 + cpu = 0.1 virtual_router_id = opennebula_virtual_router.test.id } @@ -375,15 +446,15 @@ resource "opennebula_virtual_router_instance" "test2" { } resource "opennebula_virtual_router" "test" { - name = "testacc-vr" - permissions = "642" - group = "oneadmin" + name = "testacc-vr" + permissions = "642" + group = "oneadmin" - instance_template_id = opennebula_virtual_router_instance_template.test.id + instance_template_id = opennebula_virtual_router_instance_template.test.id - tags = { - customer = "1" - } + tags = { + customer = "1" + } } ` @@ -393,8 +464,8 @@ resource "opennebula_virtual_router_instance" "test" { name = "testacc-vr-virtual-machine" group = "oneadmin" permissions = "642" - memory = 128 - cpu = 0.1 + memory = 128 + cpu = 0.1 virtual_router_id = opennebula_virtual_router.test.id } @@ -404,8 +475,8 @@ resource "opennebula_virtual_router_instance" "test2" { name = "testacc-vr-virtual-machine-2" group = "oneadmin" permissions = "642" - memory = 128 - cpu = 0.1 + memory = 128 + cpu = 0.1 virtual_router_id = opennebula_virtual_router.test.id @@ -415,15 +486,15 @@ resource "opennebula_virtual_router_instance" "test2" { } resource "opennebula_virtual_router" "test" { - name = "testacc-vr" - permissions = "642" - group = "oneadmin" + name = "testacc-vr" + permissions = "642" + group = "oneadmin" - instance_template_id = opennebula_virtual_router_instance_template.test.id + instance_template_id = opennebula_virtual_router_instance_template.test.id - tags = { - customer = "1" - } + tags = { + customer = "1" + } } ` @@ -433,8 +504,8 @@ resource "opennebula_virtual_router_instance" "test" { name = "testacc-vr-virtual-machine" group = "oneadmin" permissions = "642" - memory = 128 - cpu = 0.1 + memory = 128 + cpu = 0.1 virtual_router_id = opennebula_virtual_router.test.id } @@ -444,34 +515,34 @@ resource "opennebula_virtual_router_instance" "test2" { name = "testacc-vr-virtual-machine-2" group = "oneadmin" permissions = "642" - memory = 128 - cpu = 0.1 + memory = 128 + cpu = 0.1 virtual_router_id = opennebula_virtual_router.test.id } resource "opennebula_virtual_router" "test" { - name = "testacc-vr" - permissions = "642" - group = "oneadmin" + name = "testacc-vr" + permissions = "642" + group = "oneadmin" - instance_template_id = opennebula_virtual_router_instance_template.test.id + instance_template_id = opennebula_virtual_router_instance_template.test.id - tags = { - customer = "1" - } + tags = { + customer = "1" + } } resource "opennebula_virtual_router_nic" "nic2" { - virtual_router_id = opennebula_virtual_router.test.id - network_id = opennebula_virtual_network.network2.id + virtual_router_id = opennebula_virtual_router.test.id + network_id = opennebula_virtual_network.network2.id } resource "opennebula_virtual_router_nic" "nic1" { - floating_ip = true - floating_only = true - virtual_router_id = opennebula_virtual_router.test.id - network_id = opennebula_virtual_network.network1.id + floating_ip = true + floating_only = true + virtual_router_id = opennebula_virtual_router.test.id + network_id = opennebula_virtual_network.network1.id } ` var testAccVirtualRouterUpdateNICs = testAccVirtualRouterMachineTemplate + testAccVirtualRouterVNet + ` @@ -480,8 +551,8 @@ resource "opennebula_virtual_router_instance" "test" { name = "testacc-vr-virtual-machine" group = "oneadmin" permissions = "642" - memory = 128 - cpu = 0.1 + memory = 128 + cpu = 0.1 virtual_router_id = opennebula_virtual_router.test.id } @@ -491,22 +562,22 @@ resource "opennebula_virtual_router_instance" "test2" { name = "testacc-vr-virtual-machine-2" group = "oneadmin" permissions = "642" - memory = 128 - cpu = 0.1 + memory = 128 + cpu = 0.1 virtual_router_id = opennebula_virtual_router.test.id } resource "opennebula_virtual_router" "test" { - name = "testacc-vr" - permissions = "642" - group = "oneadmin" + name = "testacc-vr" + permissions = "642" + group = "oneadmin" - instance_template_id = opennebula_virtual_router_instance_template.test.id + instance_template_id = opennebula_virtual_router_instance_template.test.id - tags = { - customer = "1" - } + tags = { + customer = "1" + } } resource "opennebula_virtual_router_nic" "nic2" { @@ -520,3 +591,110 @@ resource "opennebula_virtual_router_nic" "nic1" { network_id = opennebula_virtual_network.network1.id } ` + +var testAccVirtualRouterDeleteSecondVrouter = testAccVirtualRouterMachineTemplate + testAccVirtualRouterVNet + ` + +resource "opennebula_virtual_router_instance" "test" { + name = "testacc-vr-virtual-machine" + group = "oneadmin" + permissions = "642" + memory = 128 + cpu = 0.1 + + virtual_router_id = opennebula_virtual_router.test.id +} + +resource "opennebula_virtual_router" "test" { + name = "testacc-vr" + permissions = "642" + group = "oneadmin" + + instance_template_id = opennebula_virtual_router_instance_template.test.id + + tags = { + customer = "1" + } +} +` + +var testAccVirtualRouterAddNICsWithIPs = testAccVirtualRouterMachineTemplate + testAccVirtualRouterVNet + ` + +resource "opennebula_virtual_router_instance" "test" { + name = "testacc-vr-virtual-machine" + group = "oneadmin" + permissions = "642" + memory = 128 + cpu = 0.1 + + virtual_router_id = opennebula_virtual_router.test.id +} + +resource "opennebula_virtual_router" "test" { + name = "testacc-vr" + permissions = "642" + group = "oneadmin" + + instance_template_id = opennebula_virtual_router_instance_template.test.id + + tags = { + customer = "1" + } +} + +resource "opennebula_virtual_router_nic" "nic_floating_ip_specified" { + depends_on = [opennebula_virtual_router_instance.test] + ip = "172.16.100.160" + floating_ip = true + virtual_router_id = opennebula_virtual_router.test.id + network_id = opennebula_virtual_network.network3.id +} +` + +var testAccVirtualRouterUpdateNICsWithIPs = testAccVirtualRouterMachineTemplate + testAccVirtualRouterVNet + ` + +resource "opennebula_virtual_router_instance" "test" { + name = "testacc-vr-virtual-machine" + group = "oneadmin" + permissions = "642" + memory = 128 + cpu = 0.1 + + virtual_router_id = opennebula_virtual_router.test.id +} + +resource "opennebula_virtual_router" "test" { + name = "testacc-vr" + permissions = "642" + group = "oneadmin" + + instance_template_id = opennebula_virtual_router_instance_template.test.id + + tags = { + customer = "1" + } +} + +resource "opennebula_virtual_router_nic" "nic_IP_specified" { + depends_on = [opennebula_virtual_router_instance.test] + ip = "172.16.100.120" + virtual_router_id = opennebula_virtual_router.test.id + network_id = opennebula_virtual_network.network2.id +} + +resource "opennebula_virtual_router_nic" "nic_floating_only_IP_specified" { + depends_on = [opennebula_virtual_router_instance.test] + ip = "172.16.100.121" + floating_ip = true + floating_only = true + virtual_router_id = opennebula_virtual_router.test.id + network_id = opennebula_virtual_network.network2.id +} + +resource "opennebula_virtual_router_nic" "nic_floating_ip_specified" { + depends_on = [opennebula_virtual_router_instance.test] + ip = "172.16.100.160" + floating_ip = true + virtual_router_id = opennebula_virtual_router.test.id + network_id = opennebula_virtual_network.network3.id +} +`