diff --git a/opennebula/helpers_vm.go b/opennebula/helpers_vm.go index 1493f609e..35eed7368 100644 --- a/opennebula/helpers_vm.go +++ b/opennebula/helpers_vm.go @@ -217,13 +217,17 @@ func vmDiskResize(ctx context.Context, vmc *goca.VMController, timeout time.Dura // vmNICAttach is an helper that synchronously attach a nic func vmNICAttach(ctx context.Context, vmc *goca.VMController, timeout time.Duration, nicTpl *shared.NIC) (int, error) { - networkID, err := nicTpl.GetI(shared.NetworkID) - if err != nil { - return -1, fmt.Errorf("NIC template doesn't have a network ID") + networkMode, netModeErr := nicTpl.Get(shared.NetworkMode) + networkID, netIDErr := nicTpl.GetI(shared.NetworkID) + if netIDErr == nil { + log.Printf("[DEBUG] Attach NIC to network (ID:%d)", networkID) + } else { + if netModeErr != nil { + return -1, fmt.Errorf("NIC template neither have a network ID or a network mode") + } + log.Printf("[DEBUG] Attach NIC witn %s network mode", networkMode) } - log.Printf("[DEBUG] Attach NIC to network (ID:%d)", networkID) - // Retrieve NIC list vm, err := vmc.Info(false) if err != nil { diff --git a/opennebula/resource_opennebula_virtual_machine.go b/opennebula/resource_opennebula_virtual_machine.go index 2c21f4fdc..3698df408 100644 --- a/opennebula/resource_opennebula_virtual_machine.go +++ b/opennebula/resource_opennebula_virtual_machine.go @@ -104,6 +104,18 @@ func nicComputedVMFields() map[string]*schema.Schema { Type: schema.TypeInt, }, }, + //"computed_network_mode_auto": { + // Type: schema.TypeBool, + // Computed: true, + //}, + //"computed_sched_requirements": { + // Type: schema.TypeString, + // Computed: true, + //}, + //"computed_sched_rank": { + // Type: schema.TypeString, + // Computed: true, + //}, } } @@ -123,6 +135,10 @@ func templateNICVMSchema() *schema.Schema { Type: schema.TypeString, Computed: true, }, + //"network_mode_auto": { + // Type: schema.TypeBool, + // Computed: true, + //}, }), }, } @@ -902,6 +918,21 @@ func flattenVMNICComputed(NICConfig map[string]interface{}, NIC shared.NIC) map[ NICMap["security_groups"] = NICMap["computed_security_groups"] } + networkMode, err := NIC.Get(shared.NetworkMode) + if err == nil && networkMode == "auto" { + NICMap["network_mode_auto"] = true + } + + schedReqs, err := NIC.Get(shared.SchedRequirements) + if err == nil { + NICMap["sched_requirements"] = schedReqs + } + + schedRank, err := NIC.Get(shared.SchedRank) + if err == nil { + NICMap["sched_rank"] = schedRank + } + return NICMap } @@ -940,6 +971,10 @@ func matchNIC(NICConfig map[string]interface{}, NIC shared.NIC) bool { model, _ := NIC.Get(shared.Model) virtioQueues, _ := NIC.GetStr("VIRTIO_QUEUES") + schedRequirements, _ := NIC.Get(shared.SchedRequirements) + schedRank, _ := NIC.Get(shared.SchedRank) + networkMode, _ := NIC.Get(shared.NetworkMode) + securityGroupsArray, _ := NIC.Get(shared.SecurityGroups) if NICConfig["security_groups"] != nil && len(NICConfig["security_groups"].([]interface{})) > 0 { @@ -976,7 +1011,10 @@ func matchNIC(NICConfig map[string]interface{}, NIC shared.NIC) bool { emptyOrEqual(NICConfig["mac"], mac) && emptyOrEqual(NICConfig["physical_device"], physicalDevice) && emptyOrEqual(NICConfig["model"], model) && - emptyOrEqual(NICConfig["virtio_queues"], virtioQueues) + emptyOrEqual(NICConfig["virtio_queues"], virtioQueues) && + emptyOrEqual(NICConfig["sched_requirements"], schedRequirements) && + emptyOrEqual(NICConfig["sched_rank"], schedRank) && + (NICConfig["network_mode_auto"].(bool) == false || networkMode == "auto") } func matchNICComputed(NICConfig map[string]interface{}, NIC shared.NIC) bool { @@ -1051,8 +1089,13 @@ NICLoop: match = true nicMap = flattenVMNICComputed(nicConfig, nic) - networkID, _ := nic.GetI(shared.NetworkID) - nicMap["network_id"] = networkID + networkIDCfg := nicConfig["network_id"].(int) + if networkIDCfg == -1 { + nicMap["network_id"] = -1 + } else { + networkID, _ := nic.GetI(shared.NetworkID) + nicMap["network_id"] = networkID + } nicList = append(nicList, nicMap) @@ -1863,7 +1906,11 @@ func updateNIC(ctx context.Context, d *schema.ResourceData, meta interface{}) er "security_groups", "model", "virtio_queues", - "physical_device") + "physical_device", + "network_mode_auto", + "sched_requirements", + "sched_rank", + ) // in case of NICs updated in the middle of the NIC list // they would be reattached at the end of the list (we don't have in place XML-RPC update method). diff --git a/opennebula/resource_opennebula_virtual_machine_nic_test.go b/opennebula/resource_opennebula_virtual_machine_nic_test.go index f7a88e51e..14b7fcebd 100644 --- a/opennebula/resource_opennebula_virtual_machine_nic_test.go +++ b/opennebula/resource_opennebula_virtual_machine_nic_test.go @@ -60,11 +60,11 @@ func TestAccVirtualMachineNICUpdate(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "name", "test-virtual_machine"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "keep_nic_order", "false"), - resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.#", "4"), + resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.#", "5"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.0.computed_ip", "172.16.100.112"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.1.computed_ip", "172.16.100.132"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.2.computed_ip", "172.16.100.113"), - resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.3.computed_ip", "172.16.100.133"), + resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.4.computed_ip", "172.16.100.133"), ), }, { @@ -72,11 +72,11 @@ func TestAccVirtualMachineNICUpdate(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "name", "test-virtual_machine"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "keep_nic_order", "true"), - resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.#", "4"), + resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.#", "5"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.0.computed_ip", "172.16.100.112"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.1.computed_ip", "172.16.100.134"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.2.computed_ip", "172.16.100.113"), - resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.3.computed_ip", "172.16.100.133"), + resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "nic.4.computed_ip", "172.16.100.133"), ), }, { @@ -105,7 +105,7 @@ func TestAccVirtualMachineTemplateNIC(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccSetDSdummy(), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "name", "test-virtual_machine"), - resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.#", "1"), + resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.#", "2"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.0.computed_ip", "172.16.100.131"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.0.computed_model", "virtio"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.0.computed_virtio_queues", "2"), @@ -116,7 +116,7 @@ func TestAccVirtualMachineTemplateNIC(t *testing.T) { Config: testAccVirtualMachineTemplateNICAdd, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "name", "test-virtual_machine"), - resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.#", "1"), + resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.#", "2"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.0.computed_ip", "172.16.100.131"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.0.computed_model", "virtio"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.0.computed_virtio_queues", "2"), @@ -130,7 +130,7 @@ func TestAccVirtualMachineTemplateNIC(t *testing.T) { Config: testAccVirtualMachineTemplateNIC, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "name", "test-virtual_machine"), - resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.#", "1"), + resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.#", "2"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.0.computed_ip", "172.16.100.131"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.0.computed_model", "virtio"), resource.TestCheckResourceAttr("opennebula_virtual_machine.test", "template_nic.0.computed_virtio_queues", "2"), @@ -445,6 +445,9 @@ var testAccVirtualMachineTemplateConfigMultipleNICs = testNICVNetResources + ` network_id = opennebula_virtual_network.network2.id ip = "172.16.100.113" } + nic { + network_mode_auto = true + } nic { network_id = opennebula_virtual_network.network1.id ip = "172.16.100.133" @@ -497,6 +500,9 @@ var testAccVirtualMachineTemplateConfigMultipleNICsOrderedUpdate = testNICVNetRe network_id = opennebula_virtual_network.network2.id ip = "172.16.100.113" } + nic { + network_mode_auto = true + } nic { network_id = opennebula_virtual_network.network1.id ip = "172.16.100.133" @@ -568,6 +574,9 @@ resource "opennebula_template" "template" { model = "virtio" virtio_queues = "2" } + nic { + network_mode_auto = true + } os { arch = "x86_64" diff --git a/opennebula/shared_schemas.go b/opennebula/shared_schemas.go index df279d516..e9e0d64e4 100644 --- a/opennebula/shared_schemas.go +++ b/opennebula/shared_schemas.go @@ -207,7 +207,8 @@ func nicFields() map[string]*schema.Schema { }, "network_id": { Type: schema.TypeInt, - Required: true, + Optional: true, + Default: -1, }, "network": { Type: schema.TypeString, @@ -224,6 +225,18 @@ func nicFields() map[string]*schema.Schema { Type: schema.TypeInt, }, }, + "network_mode_auto": { + Type: schema.TypeBool, + Optional: true, + }, + "sched_requirements": { + Type: schema.TypeString, + Optional: true, + }, + "sched_rank": { + Type: schema.TypeString, + Optional: true, + }, } } @@ -536,7 +549,10 @@ func makeNICVector(nicConfig map[string]interface{}) *shared.NIC { for k, v := range nicConfig { if k == "network_id" { - nic.Add(shared.NetworkID, strconv.Itoa(v.(int))) + networkID := v.(int) + if networkID != -1 { + nic.Add(shared.NetworkID, strconv.Itoa(networkID)) + } continue } @@ -558,6 +574,15 @@ func makeNICVector(nicConfig map[string]interface{}) *shared.NIC { case "security_groups": nicSecGroups := ArrayToString(v.([]interface{}), ",") nic.Add(shared.SecurityGroups, nicSecGroups) + case "network_mode_auto": + if v.(bool) { + nic.Add(shared.NetworkMode, "auto") + } + case "sched_requirements": + nic.Add(shared.SchedRequirements, v.(string)) + case "sched_rank": + nic.Add(shared.SchedRank, v.(string)) + } } @@ -774,8 +799,17 @@ func flattenNIC(nic shared.NIC) map[string]interface{} { model, _ := nic.Get(shared.Model) virtioQueues, _ := nic.GetStr("VIRTIO_QUEUES") networkId, _ := nic.GetI(shared.NetworkID) - securityGroupsArray, _ := nic.Get(shared.SecurityGroups) + networkModeBool := false + networkMode, err := nic.Get(shared.NetworkMode) + if err == nil && networkMode == "auto" { + networkModeBool = true + } + + schedReqs, _ := nic.Get(shared.SchedRequirements) + schedRank, _ := nic.Get(shared.SchedRank) + + securityGroupsArray, _ := nic.Get(shared.SecurityGroups) if len(securityGroupsArray) > 0 { sgString := strings.Split(securityGroupsArray, ",") for _, s := range sgString { @@ -785,14 +819,17 @@ func flattenNIC(nic shared.NIC) map[string]interface{} { } return map[string]interface{}{ - "ip": ip, - "mac": mac, - "network_id": networkId, - "physical_device": physicalDevice, - "network": network, - "model": model, - "virtio_queues": virtioQueues, - "security_groups": sg, + "ip": ip, + "mac": mac, + "network_id": networkId, + "physical_device": physicalDevice, + "network": network, + "model": model, + "virtio_queues": virtioQueues, + "security_groups": sg, + "network_mode_auto": networkModeBool, + "sched_requirements": schedReqs, + "sched_rank": schedRank, } }