102 lines
2.7 KiB
Go
102 lines
2.7 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/Cadoles/goca"
|
||
|
"github.com/hashicorp/packer/common"
|
||
|
"github.com/hashicorp/packer/helper/config"
|
||
|
"github.com/hashicorp/packer/packer"
|
||
|
"github.com/hashicorp/packer/template/interpolate"
|
||
|
)
|
||
|
|
||
|
// Config handles configuration options of the OpenNebula post-processor
|
||
|
type Config struct {
|
||
|
common.PackerConfig `mapstructure:",squash"`
|
||
|
User string
|
||
|
Password string
|
||
|
Endpoint string
|
||
|
ImageName string `mapstructure:"image_name"`
|
||
|
ImageTemplate []string `mapstructure:"image_template"`
|
||
|
DatastoreName string `mapstructure:"datastore_name"`
|
||
|
MergeTemplate bool `mapstructure:"merge_template"`
|
||
|
ctx interpolate.Context
|
||
|
}
|
||
|
|
||
|
// PostProcessor is an OpenNebula post processor for packer
|
||
|
type PostProcessor struct {
|
||
|
Conf *Config
|
||
|
}
|
||
|
|
||
|
// Configure configures the packer OpenNebula post-processor
|
||
|
func (pp *PostProcessor) Configure(raws ...interface{}) error {
|
||
|
conf := &Config{}
|
||
|
err := config.Decode(conf, &config.DecodeOpts{
|
||
|
Interpolate: true,
|
||
|
InterpolateContext: &conf.ctx,
|
||
|
}, raws...)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
pp.Conf = conf
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
// PostProcess creates/updates your configured image to OpenNebula using the XML-RPC API
|
||
|
func (pp *PostProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Artifact, bool, error) {
|
||
|
|
||
|
// Initialize OpenNebula XML-RPC API client
|
||
|
config := goca.NewConfig(pp.Conf.User, pp.Conf.Password, pp.Conf.Endpoint)
|
||
|
if err := goca.SetClient(config); err != nil {
|
||
|
return a, true, err
|
||
|
}
|
||
|
|
||
|
// Search image template by its name
|
||
|
img, err := goca.NewImageFromName(pp.Conf.ImageName)
|
||
|
if err != nil && err.Error() != "resource not found" {
|
||
|
return a, true, err
|
||
|
}
|
||
|
|
||
|
ui.Say(fmt.Sprintf("Connecting to OpenNebula RPC endpoint '%s' with provided credentials...", pp.Conf.Endpoint))
|
||
|
|
||
|
// Generate image template
|
||
|
tmplStr := serializeImageTemplate(pp.Conf.ImageTemplate)
|
||
|
|
||
|
// Fi the image template can not be found, we create it
|
||
|
if img == nil {
|
||
|
|
||
|
ui.Say(fmt.Sprintf("The OpenNebula image template '%s' could not be found. Creating it...", pp.Conf.ImageName))
|
||
|
|
||
|
// Search image datastore's ID
|
||
|
datastore, err := goca.NewDatastoreFromName(pp.Conf.DatastoreName)
|
||
|
if err != nil {
|
||
|
return a, true, err
|
||
|
}
|
||
|
|
||
|
// Create image template
|
||
|
if _, err = goca.CreateImage(tmplStr, datastore.ID); err != nil {
|
||
|
return a, true, err
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
|
||
|
ui.Say(fmt.Sprintf("The OpenNebula image template '%s' has been found. Updating it...", pp.Conf.ImageName))
|
||
|
|
||
|
// Update image template
|
||
|
if err := img.Update(tmplStr, pp.Conf.MergeTemplate); err != nil {
|
||
|
return a, true, err
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
ui.Say("Operation completed.")
|
||
|
|
||
|
return a, true, nil
|
||
|
|
||
|
}
|
||
|
|
||
|
func serializeImageTemplate(tmpl []string) string {
|
||
|
return strings.Join(tmpl, "\n")
|
||
|
}
|