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

B #169: fix VM update template #171

Merged
merged 1 commit into from
Nov 19, 2021
Merged
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
143 changes: 130 additions & 13 deletions opennebula/resource_opennebula_virtual_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -1261,26 +1261,76 @@ func resourceOpennebulaVirtualMachineUpdate(d *schema.ResourceData, meta interfa
}

updateConf := false

// retrieve only template sections managed by updateconf method
tpl := vm.NewTemplate()
for _, name := range []string{"OS", "FEATURES", "INPUT", "GRAPHICS", "RAW", "CONTEXT"} {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why in the following lines you work only on "OS", "GRAPHICS" and "CONTEXT".
Why not "FEATURES", "INPUT" or "RAW" ?

Copy link
Collaborator Author

@treywelsh treywelsh Nov 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copy these sections only, from the existing VM template, because the method updateconf take them into account:
https://docs.opennebula.io/5.12/integration/system_interfaces/api.html#one-vm-updateconf

If I don't copy one of these fields, it would be erased. See OS deletion problem when updating CONTEXT in #169 .
The RAW field is managed through the template resource, I didn't enabled it in VM resource, here is the original issue about this section: #123
Do we need it in VM resource ?

For other parts FEATURES and INPUT there aren't managed at all.

This is not the goal of this issue, but to manage additional VM sections we could open a new issue (probably better) or just add them to #154

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perfect thx

vectors := vmInfos.Template.GetVectors(name)
for _, vec := range vectors {
tpl.Elements = append(tpl.Elements, vec)
}
}

if d.HasChange("os") {
updateConf = true

log.Printf("[DEBUG] Update os")

//Generate OS definition
addOS(tpl, d.Get("os").([]interface{}))
old, new := d.GetChange("os")
treywelsh marked this conversation as resolved.
Show resolved Hide resolved
newOSSlice := new.([]interface{})

if len(newOSSlice) == 0 {
// No os configuration to apply
tpl.Del("OS")
} else {

appliedOSSlice := old.([]interface{})

if len(appliedOSSlice) == 0 {
// No os configuration applied
addOS(tpl, newOSSlice)
} else {

newOS := newOSSlice[0].(map[string]interface{})
appliedOS := appliedOSSlice[0].(map[string]interface{})

err := updateVMTemplateVec(tpl, "OS", appliedOS, newOS)
if err != nil {
return err
}
}
}
}

if d.HasChange("graphics") {
updateConf = true

log.Printf("[DEBUG] Update graphics")

//Generate GRAPHICS definition
addGraphic(tpl, d.Get("graphics").([]interface{}))
old, new := d.GetChange("graphics")
newGraphicsSlice := new.([]interface{})

if len(newGraphicsSlice) == 0 {
// No graphics configuration to apply
tpl.Del("GRAPHICS")
} else {

appliedGraphicsSlice := old.([]interface{})

if len(appliedGraphicsSlice) == 0 {
// No graphics configuration applied
addGraphic(tpl, newGraphicsSlice)
} else {

newGraphics := newGraphicsSlice[0].(map[string]interface{})
appliedGraphics := appliedGraphicsSlice[0].(map[string]interface{})

updateVMTemplateVec(tpl, "GRAPHICS", appliedGraphics, newGraphics)
if err != nil {
return err
}
}
}
}

if d.HasChange("context") {
Expand All @@ -1289,20 +1339,42 @@ func resourceOpennebulaVirtualMachineUpdate(d *schema.ResourceData, meta interfa

log.Printf("[DEBUG] Update context")

contextVec := tpl.AddVector("CONTEXT")
old, new := d.GetChange("context")
appliedContext := old.(map[string]interface{})
newContext := new.(map[string]interface{})

//Generate CONTEXT definition
context := d.Get("context").(map[string]interface{})
if len(newContext) == 0 {
// No context configuration to apply
tpl.Del(vmk.ContextVec)
} else {

// Add new context elements to the template
for key, value := range context {
keyUp := strings.ToUpper(key)
contextVec.AddPair(keyUp, fmt.Sprint(value))
}
var contextVec *dyn.Vector
if len(appliedContext) == 0 {
// No context configuration applied
contextVec = tpl.AddVector(vmk.ContextVec)

// Add new elements
for key, value := range newContext {
keyUp := strings.ToUpper(key)

_, ok := appliedContext[keyUp]
if ok {
continue
}

contextVec.AddPair(keyUp, value)
}

} else {
updateVMTemplateVec(tpl, "CONTEXT", appliedContext, newContext)
if err != nil {
return err
}
}
}
}

if updateConf == true {
if updateConf {

timeout := d.Get("timeout").(int)

Expand Down Expand Up @@ -1344,6 +1416,51 @@ func resourceOpennebulaVirtualMachineUpdate(d *schema.ResourceData, meta interfa
return resourceOpennebulaVirtualMachineRead(d, meta)
}

// updateVMVec update a vector of an existing VM template
func updateVMTemplateVec(tpl *vm.Template, vecName string, appliedCfg, newCfg map[string]interface{}) error {

// Retrieve vector
var targetVec *dyn.Vector
vectors := tpl.GetVectors(vecName)
switch len(vectors) {
case 0:
return fmt.Errorf("No %s vector present", vecName)
case 1:
targetVec = vectors[0]

// Remove or update existing elements
for key := range appliedCfg {
keyUp := strings.ToUpper(key)

value, ok := newCfg[keyUp]
if ok {
// update existing element
targetVec.Del(keyUp)
targetVec.AddPair(keyUp, fmt.Sprint(value))
} else {
// remove element
targetVec.Del(keyUp)
}
}
default:
return fmt.Errorf("Multiple %s vectors", vecName)
}

// Add new elements
for key, value := range newCfg {
keyUp := strings.ToUpper(key)

_, ok := appliedCfg[keyUp]
if ok {
continue
}

targetVec.AddPair(keyUp, value)
}

return nil
}

func resourceOpennebulaVirtualMachineDelete(d *schema.ResourceData, meta interface{}) error {
err := resourceOpennebulaVirtualMachineRead(d, meta)
if err != nil || d.Id() == "" {
Expand Down