Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

F-72: Allow update of VM NICs and update disks for consistency #80

Merged
merged 9 commits into from
Dec 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ FEATURES:
* resources/opennebula_virtual_machine: Change 'image_id' disk attribute from Required to Optional ([#71](https://github.com/OpenNebula/terraform-provider-opennebula/issues/71))
* **New Resource**: `opennebula_service`: First implementation ([oneflow](http://docs.opennebula.io/5.12/integration/system_interfaces/appflow_api.html#service)),
* **New Resource**: `opennebula_service_template`: First implementation ([oneflow-template](http://docs.opennebula.io/5.12/integration/system_interfaces/appflow_api.html#service-template)),
* resources/opennebula_virtual_machine: Enable VM NIC update ([#72](https://github.com/OpenNebula/terraform-provider-opennebula/issues/72))

BUG FIXES:
* resources/opennebula_virtual_network: Fix Hold IPs crash ([#67](https://github.com/OpenNebula/terraform-provider-opennebula/issues/67))
Expand Down
37 changes: 37 additions & 0 deletions opennebula/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (

"github.com/OpenNebula/one/src/oca/go/src/goca/errors"
"github.com/OpenNebula/one/src/oca/go/src/goca/schemas/shared"

"github.com/hashicorp/terraform/helper/schema"
)

func inArray(val string, array []string) (index int) {
Expand Down Expand Up @@ -92,3 +94,38 @@ func NoExists(err error) bool {

return false
}

// returns the diff of two lists of schemas, making diff on attrNames only
func diffListConfig(refVecs, vecs []interface{}, s *schema.Resource, attrNames ...string) ([]interface{}, []interface{}) {

refSet := schema.NewSet(schema.HashResource(s), []interface{}{})
for _, iface := range refVecs {
sc := iface.(map[string]interface{})

// keep only attrNames values
filteredSc := make(map[string]interface{})
for _, name := range attrNames {
filteredSc[name] = sc[name]
}

refSet.Add(filteredSc)
}

set := schema.NewSet(schema.HashResource(s), []interface{}{})
for _, iface := range vecs {
sc := iface.(map[string]interface{})

// keep only attrNames values
filteredSc := make(map[string]interface{})
for _, name := range attrNames {
filteredSc[name] = sc[name]
}

set.Add(filteredSc)
}

pSet := refSet.Difference(set)
mSet := set.Difference(refSet)

return mSet.List(), pSet.List()
}
121 changes: 87 additions & 34 deletions opennebula/helpers_vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,45 +10,12 @@ import (
vmk "github.com/OpenNebula/one/src/oca/go/src/goca/schemas/vm/keys"
)

// return disk configuration with image_id that only appear on refDisks side
func disksConfigDiff(refDisks, disks []interface{}) []map[string]interface{} {

// get the list of disks ID to detach
diffConfig := make([]map[string]interface{}, 0)

for _, refDisk := range refDisks {
refDiskConfig := refDisk.(map[string]interface{})
refImageID := refDiskConfig["image_id"].(int)
// If the disk exists with Default ID, skip it
if refImageID < 0 {
continue
}

diff := true
for _, disk := range disks {
diskConfig := disk.(map[string]interface{})
diskImageID := diskConfig["image_id"].(int)

if refImageID == diskImageID {
diff = false
break
}
}

if diff {
diffConfig = append(diffConfig, refDiskConfig)
}
}

return diffConfig
}

// vmDiskAttach is an helper that synchronously attach a disk
func vmDiskAttach(vmc *goca.VMController, timeout int, diskTpl *shared.Disk) error {

imageID, err := diskTpl.GetI(shared.ImageID)
if err != nil {
return fmt.Errorf("disk template doesn't have and image ID")
return fmt.Errorf("disk template doesn't have an image ID")
}

log.Printf("[DEBUG] Attach image (ID:%d) as disk", imageID)
Expand Down Expand Up @@ -128,3 +95,89 @@ func vmDiskDetach(vmc *goca.VMController, timeout int, diskID int) error {

return nil
}

// vmNICAttach is an helper that synchronously attach a nic
func vmNICAttach(vmc *goca.VMController, timeout int, nicTpl *shared.NIC) error {

networkID, err := nicTpl.GetI(shared.NetworkID)
if err != nil {
return fmt.Errorf("NIC template doesn't have a network ID")
}

log.Printf("[DEBUG] Attach NIC to network (ID:%d)", networkID)

err = vmc.AttachNIC(nicTpl.String())
if err != nil {
return fmt.Errorf("can't attach network with ID:%d: %s\n", networkID, err)
}

// wait before checking NIC
_, err = waitForVMState(vmc, timeout, vmNICUpdateReadyStates...)
if err != nil {
return fmt.Errorf(
"waiting for virtual machine (ID:%d) to be in state %s: %s", vmc.ID, strings.Join(vmNICUpdateReadyStates, " "), err)
}

// Check that NIC is attached
vm, err := vmc.Info(false)
if err != nil {
return err
}

for _, attachedNic := range vm.Template.GetNICs() {

attachedNicNetworkID, _ := attachedNic.GetI(shared.NetworkID)
if attachedNicNetworkID == networkID {
return nil
}
}

// If NIC not attached, retrieve error message
vmerr, _ := vm.UserTemplate.Get(vmk.Error)

return fmt.Errorf("network ID %d: %s", networkID, vmerr)
}

// vmNICDetach is an helper that synchronously detach a NIC
func vmNICDetach(vmc *goca.VMController, timeout int, nicID int) error {

log.Printf("[DEBUG] Detach NIC %d", nicID)

err := vmc.DetachNIC(nicID)
if err != nil {
return fmt.Errorf("can't detach NIC %d: %s\n", nicID, err)
}

// wait before checking NIC
_, err = waitForVMState(vmc, timeout, vmNICUpdateReadyStates...)
if err != nil {
return fmt.Errorf(
"waiting for virtual machine (ID:%d) to be in state %s: %s", vmc.ID, strings.Join(vmNICUpdateReadyStates, " "), err)
}

// Check that NIC is detached
vm, err := vmc.Info(false)
if err != nil {
return err
}

detached := true
for _, attachedNIC := range vm.Template.GetNICs() {

attachedNICID, _ := attachedNIC.ID()
if attachedNICID == nicID {
detached = false
break
}

}

if !detached {
// If NIC still attached, retrieve error message
vmerr, _ := vm.UserTemplate.Get(vmk.Error)

return fmt.Errorf("NIC %d: %s", nicID, vmerr)
}

return nil
}
32 changes: 32 additions & 0 deletions opennebula/resource_opennebula_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,38 @@ func resourceOpennebulaTemplateRead(d *schema.ResourceData, meta interface{}) er
return err
}

// Nics
nics := tpl.Template.GetNICs()
nicList := make([]interface{}, 0, len(nics))

// Set Nics to resource
for _, nic := range nics {
nicList = append(nicList, flattenNIC(nic))
}

if len(nicList) > 0 {
err = d.Set("nic", nicList)
if err != nil {
return err
}
}

// Set Disks to resource
disks := tpl.Template.GetDisks()
diskList := make([]interface{}, 0, len(disks))

// Set Disks to resource
for _, disk := range disks {
diskList = append(diskList, flattenDisk(disk))
}

if len(diskList) > 0 {
err = d.Set("disk", diskList)
if err != nil {
return err
}
}

err = flattenTemplate(d, &tpl.Template, true)
if err != nil {
return err
Expand Down
Loading