Merge pull request #9045 from lausser/cloud-init

feat(proxmox): add ability to add a cloud-init drive
This commit is contained in:
Wilken Rivera 2020-04-17 14:09:02 -04:00 committed by GitHub
commit cc367bd0b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 99 additions and 0 deletions

View File

@ -58,6 +58,9 @@ type Config struct {
TemplateDescription string `mapstructure:"template_description"` TemplateDescription string `mapstructure:"template_description"`
UnmountISO bool `mapstructure:"unmount_iso"` UnmountISO bool `mapstructure:"unmount_iso"`
CloudInit bool `mapstructure:"cloud_init"`
CloudInitStoragePool string `mapstructure:"cloud_init_storage_pool"`
shouldUploadISO bool shouldUploadISO bool
ctx interpolate.Context ctx interpolate.Context
@ -85,6 +88,8 @@ type vgaConfig struct {
func (c *Config) Prepare(raws ...interface{}) ([]string, error) { func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
// Agent defaults to true // Agent defaults to true
c.Agent = true c.Agent = true
// Do not add a cloud-init cdrom by default
c.CloudInit = false
var md mapstructure.Metadata var md mapstructure.Metadata
err := config.Decode(c, &config.DecodeOpts{ err := config.Decode(c, &config.DecodeOpts{

View File

@ -95,6 +95,8 @@ type FlatConfig struct {
TemplateName *string `mapstructure:"template_name" cty:"template_name"` TemplateName *string `mapstructure:"template_name" cty:"template_name"`
TemplateDescription *string `mapstructure:"template_description" cty:"template_description"` TemplateDescription *string `mapstructure:"template_description" cty:"template_description"`
UnmountISO *bool `mapstructure:"unmount_iso" cty:"unmount_iso"` UnmountISO *bool `mapstructure:"unmount_iso" cty:"unmount_iso"`
CloudInit *bool `mapstructure:"cloud_init" cty:"cloud_init"`
CloudInitStoragePool *string `mapstructure:"cloud_init_storage_pool" cty:"cloud_init_storage_pool"`
} }
// FlatMapstructure returns a new FlatConfig. // FlatMapstructure returns a new FlatConfig.
@ -195,6 +197,8 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"template_name": &hcldec.AttrSpec{Name: "template_name", Type: cty.String, Required: false}, "template_name": &hcldec.AttrSpec{Name: "template_name", Type: cty.String, Required: false},
"template_description": &hcldec.AttrSpec{Name: "template_description", Type: cty.String, Required: false}, "template_description": &hcldec.AttrSpec{Name: "template_description", Type: cty.String, Required: false},
"unmount_iso": &hcldec.AttrSpec{Name: "unmount_iso", Type: cty.Bool, Required: false}, "unmount_iso": &hcldec.AttrSpec{Name: "unmount_iso", Type: cty.Bool, Required: false},
"cloud_init": &hcldec.AttrSpec{Name: "cloud_init", Type: cty.Bool, Required: false},
"cloud_init_storage_pool": &hcldec.AttrSpec{Name: "cloud_init_storage_pool", Type: cty.String, Required: false},
} }
return s return s
} }

View File

@ -125,6 +125,9 @@ func TestBasicExampleFromDocsIsValid(t *testing.T) {
if b.config.SCSIController != "lsi" { if b.config.SCSIController != "lsi" {
t.Errorf("Expected SCSI controller to be 'lsi', got %s", b.config.SCSIController) t.Errorf("Expected SCSI controller to be 'lsi', got %s", b.config.SCSIController)
} }
if b.config.CloudInit != false {
t.Errorf("Expected CloudInit to be false, got %t", b.config.CloudInit)
}
} }
func TestAgentSetToFalse(t *testing.T) { func TestAgentSetToFalse(t *testing.T) {

View File

@ -56,6 +56,43 @@ func (s *stepFinalizeTemplateConfig) Run(ctx context.Context, state multistep.St
changes["ide2"] = "none,media=cdrom" changes["ide2"] = "none,media=cdrom"
} }
if c.CloudInit {
vmParams, err := client.GetVmConfig(vmRef)
if err != nil {
err := fmt.Errorf("Error fetching template config: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
cloudInitStoragePool := c.CloudInitStoragePool
if cloudInitStoragePool == "" {
if vmParams["bootdisk"] != nil && vmParams[vmParams["bootdisk"].(string)] != nil {
bootDisk := vmParams[vmParams["bootdisk"].(string)].(string)
cloudInitStoragePool = strings.Split(bootDisk, ":")[0]
}
}
if cloudInitStoragePool != "" {
ideControllers := []string{"ide3", "ide2", "ide1", "ide0"}
cloudInitAttached := false
// find a free ide controller
for _, controller := range ideControllers {
if vmParams[controller] == nil {
ui.Say("Adding a cloud-init cdrom in storage pool " + cloudInitStoragePool)
changes[controller] = cloudInitStoragePool + ":cloudinit"
cloudInitAttached = true
break
}
}
if cloudInitAttached == false {
err := fmt.Errorf("Found no free ide controller for a cloud-init cdrom")
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
}
}
if len(changes) > 0 { if len(changes) > 0 {
_, err := client.SetVmConfig(vmRef, changes) _, err := client.SetVmConfig(vmRef, changes)
if err != nil { if err != nil {

View File

@ -71,6 +71,51 @@ func TestTemplateFinalize(t *testing.T) {
}, },
expectedAction: multistep.ActionContinue, expectedAction: multistep.ActionContinue,
}, },
{
name: "all options with cloud-init",
builderConfig: &Config{
TemplateName: "my-template",
TemplateDescription: "some-description",
UnmountISO: true,
CloudInit: true,
},
initialVMConfig: map[string]interface{}{
"name": "dummy",
"description": "Packer ephemeral build VM",
"ide2": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
"bootdisk": "virtio0",
"virtio0": "ceph01:base-223-disk-0,cache=unsafe,media=disk,size=32G",
},
expectCallSetConfig: true,
expectedVMConfig: map[string]interface{}{
"name": "my-template",
"description": "some-description",
"ide2": "none,media=cdrom",
"ide3": "ceph01:cloudinit",
},
expectedAction: multistep.ActionContinue,
},
{
name: "no available controller for cloud-init drive",
builderConfig: &Config{
TemplateName: "my-template",
TemplateDescription: "some-description",
UnmountISO: false,
CloudInit: true,
},
initialVMConfig: map[string]interface{}{
"name": "dummy",
"description": "Packer ephemeral build VM",
"ide0": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
"ide1": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
"ide2": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
"ide3": "local:iso/Fedora-Server-dvd-x86_64-29-1.2.iso,media=cdrom",
"bootdisk": "virtio0",
"virtio0": "ceph01:base-223-disk-0,cache=unsafe,media=disk,size=32G",
},
expectCallSetConfig: false,
expectedAction: multistep.ActionHalt,
},
{ {
name: "no cd-drive with unmount=true should returns halt", name: "no cd-drive with unmount=true should returns halt",
builderConfig: &Config{ builderConfig: &Config{

View File

@ -193,6 +193,11 @@ builder.
`lsi53c810`, `virtio-scsi-pci`, `virtio-scsi-single`, `megasas`, or `pvscsi`. `lsi53c810`, `virtio-scsi-pci`, `virtio-scsi-single`, `megasas`, or `pvscsi`.
Defaults to `lsi`. Defaults to `lsi`.
- `cloud_init` (bool) - If true, add a Cloud-Init CDROM drive after the virtual machine has been converted to a template.
- `cloud_init_storage_pool` - (string) - Name of the Proxmox storage pool
to store the Cloud-Init CDROM on. If not given, the storage pool of the boot device will be used.
## Example: Fedora with kickstart ## Example: Fedora with kickstart
Here is a basic example creating a Fedora 29 server image with a Kickstart Here is a basic example creating a Fedora 29 server image with a Kickstart