From 638cd2dd44ef278940fb75f57ea5bc2dd3fa225b Mon Sep 17 00:00:00 2001 From: Jon Henry Date: Sat, 23 Jul 2016 01:23:12 -0400 Subject: [PATCH] Fixes #16, export as template --- Godeps/Godeps.json | 10 ++-- README.md | 2 + build.sh | 2 +- builder/xenserver/common/common_config.go | 9 ++-- builder/xenserver/common/step_export.go | 63 +++++++++++++++++++---- examples/centos-6.6.json | 3 +- examples/centos-7.json | 7 ++- 7 files changed, 73 insertions(+), 23 deletions(-) diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index b6c50965..6a9c4dcc 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -161,6 +161,11 @@ "ImportPath": "github.com/packer-community/winrmcp/winrmcp", "Rev": "f1bcf36a69fa2945e65dd099eee11b560fbd3346" }, + { + "ImportPath": "github.com/pkg/errors", + "Comment": "v0.7.0-5-ga2d6902", + "Rev": "a2d6902c6d2a2f194eb3fb474981ab7867c81505" + }, { "ImportPath": "github.com/pkg/sftp", "Rev": "57fcf4a640a942eb05181f929601f8f4409eda3e" @@ -213,11 +218,6 @@ { "ImportPath": "golang.org/x/sys/unix", "Rev": "50c6bc5e4292a1d4e65c6e9be5f53be28bcbe28e" - }, - { - "ImportPath": "github.com/pkg/errors", - "Comment": "v0.7.0-5-ga2d6902", - "Rev": "a2d6902c6d2a2f194eb3fb474981ab7867c81505" } ] } diff --git a/README.md b/README.md index 7528a277..df420ba0 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ A brief explanation of what the config parameters mean: * `vm_vcpus` - the number of vCPUs to assign during build * `vm_disks` - a nested array of disk name: capacity pairs. Allows creating more than one virtual disk, and assigning each a name. If disk_size is also present, it takes priority and this setting is completely ignored. Using arrays enforces drive creation order, which can be very important for matching up to device names in Kickstart scripts, for example. * `nfs_mount` - Used for VHD artifacts, the NFS mount for the sr_name + * `convert_to_template` - Convert the VM to a Template before final export. Boolean. Once you've updated the config file with your own parameters, you can use packer to build this VM with the following command: @@ -144,6 +145,7 @@ A brief explanation of what the config parameters mean: * `vm_name` - the name that should be given to the created VM. * `source_vm` - the name of the VM to clone and operate on * `nfs_mount` - Used for VHD artifacts, the NFS mount for the sr_name + * `convert_to_template` - Convert the VM to a Template before final export. Boolean. Once you've updated the config file with your own parameters, you can use packer to build this VM with the following command: diff --git a/build.sh b/build.sh index 1eb3d586..4dfb3d33 100755 --- a/build.sh +++ b/build.sh @@ -39,7 +39,7 @@ IFS=$OLDIFS # Copy our OS/Arch to the bin/ directory echo "==> Copying binaries for this platform..." -DEV_PLATFORM="./pkg/$(go env GOOS)_$(go env GOARCH)" +DEV_PLATFORM="./pkg/${XC_OS}_${XC_ARCH}" for F in $(find ${DEV_PLATFORM} -mindepth 1 -maxdepth 1 -type f); do cp -v ${F} bin/ cp -v ${F} ${MAIN_GOPATH}/bin/ diff --git a/builder/xenserver/common/common_config.go b/builder/xenserver/common/common_config.go index 8294d93b..8fbdc20f 100644 --- a/builder/xenserver/common/common_config.go +++ b/builder/xenserver/common/common_config.go @@ -50,10 +50,11 @@ type CommonConfig struct { RawSSHWaitTimeout string `mapstructure:"ssh_wait_timeout"` SSHWaitTimeout time.Duration - OutputDir string `mapstructure:"output_directory"` - Format string `mapstructure:"format"` - KeepVM string `mapstructure:"keep_vm"` - IPGetter string `mapstructure:"ip_getter"` + OutputDir string `mapstructure:"output_directory"` + Format string `mapstructure:"format"` + KeepVM string `mapstructure:"keep_vm"` + IPGetter string `mapstructure:"ip_getter"` + ConvertToTemplate bool `mapstructure:"convert_to_template"` } func (c *CommonConfig) Prepare(ctx *interpolate.Context, pc *common.PackerConfig) []error { diff --git a/builder/xenserver/common/step_export.go b/builder/xenserver/common/step_export.go index 5d8461ff..e142164e 100644 --- a/builder/xenserver/common/step_export.go +++ b/builder/xenserver/common/step_export.go @@ -87,7 +87,7 @@ func (self *StepExport) Run(state multistep.StateBag) multistep.StepAction { suffix := ".vhd" extrauri := "&format=vhd" - exportFiles := make([]string, 0, 1) + exportFiles := make([]string, 0, 1) instance, err := client.GetVMByUuid(instance_uuid) if err != nil { @@ -107,6 +107,22 @@ func (self *StepExport) Run(state multistep.StateBag) multistep.StepAction { return multistep.ActionContinue case "vhd": + // Before exporting, convert it to a template (if requested) + // If a template, we assume all VIFs should be removed at export time, + // to make it more generic and reusable + if config.ConvertToTemplate { + ui.Say("Converting VM to template before export") + err = instance.SetIsATemplate(true) + if err != nil { + ui.Error(fmt.Sprintf("Error converting VM to a template prior to export: %s", err.Error())) + return multistep.ActionHalt + } + vifs, _ := instance.GetVIFs() + for _, vif := range vifs { + ui.Say("Destroying VM network interfaces for template export") + vif.Destroy() + } + } disks, err := instance.GetDisks() if err != nil { @@ -145,14 +161,28 @@ func (self *StepExport) Run(state multistep.StateBag) multistep.StepAction { return multistep.ActionHalt } - exportFiles = append(exportFiles , export_filename) - + exportFiles = append(exportFiles, export_filename) + dst.Close() } case "xva": - // export the VM - + // Before exporting, convert it to a template (if requested) + // If a template, we assume all VIFs should be removed at export time, + // to make it more generic and reusable + if config.ConvertToTemplate { + ui.Say("Converting VM to template before export") + err = instance.SetIsATemplate(true) + if err != nil { + ui.Error(fmt.Sprintf("Error converting VM to a template prior to export: %s", err.Error())) + return multistep.ActionHalt + } + vifs, _ := instance.GetVIFs() + for _, vif := range vifs { + ui.Say("Destroying VM network interfaces for template export") + vif.Destroy() + } + } export_url := fmt.Sprintf("https://%s/export?uuid=%s&session_id=%s", client.Host, instance_uuid, @@ -168,15 +198,29 @@ func (self *StepExport) Run(state multistep.StateBag) multistep.StepAction { return multistep.ActionHalt } - exportFiles = append(exportFiles , export_filename) + exportFiles = append(exportFiles, export_filename) case "vdi_raw": suffix = ".raw" extrauri = "" fallthrough case "vdi_vhd": - // export the disks - + // Before exporting, convert it to a template (if requested) + // If a template, we assume all VIFs should be removed at export time, + // to make it more generic and reusable + if config.ConvertToTemplate { + ui.Say("Converting VM to template before export") + err = instance.SetIsATemplate(true) + if err != nil { + ui.Error(fmt.Sprintf("Error converting VM to a template prior to export: %s", err.Error())) + return multistep.ActionHalt + } + vifs, _ := instance.GetVIFs() + for _, vif := range vifs { + ui.Say("Destroying VM network interfaces for template export") + vif.Destroy() + } + } disks, err := instance.GetDisks() if err != nil { ui.Error(fmt.Sprintf("Could not get VM disks: %s", err.Error())) @@ -233,7 +277,6 @@ func (self *StepExport) Run(state multistep.StateBag) multistep.StepAction { } - disk_export_filename := fmt.Sprintf("%s/%s%s", config.OutputDir, disk_uuid, suffix) ui.Say("Getting VDI " + disk_export_url) @@ -249,7 +292,7 @@ func (self *StepExport) Run(state multistep.StateBag) multistep.StepAction { } default: - panic(fmt.Sprintf("Unknown export format '%s'", self.OutputFormat )) + panic(fmt.Sprintf("Unknown export format '%s'", self.OutputFormat)) } state.Put("export_files", exportFiles) diff --git a/examples/centos-6.6.json b/examples/centos-6.6.json index 4cc09b29..361a4c36 100644 --- a/examples/centos-6.6.json +++ b/examples/centos-6.6.json @@ -23,7 +23,8 @@ "vm_description": "Build time: {{isotime}}", "vm_disks": [ ["rootvol", "40000"] - ] + ], + "convert_to_template": false } ], diff --git a/examples/centos-7.json b/examples/centos-7.json index 108f4563..0ae1e92b 100755 --- a/examples/centos-7.json +++ b/examples/centos-7.json @@ -10,7 +10,9 @@ " ks=http://10.204.137.80/ks/centos7-ks.cfg" ], "boot_wait": "10s", - "disk_size": 40960, + "vm_disks": [ + ["rootvol", "40000"] + ], "http_directory": "/var/www/html/packer", "iso_url": "http://mirrors.seas.harvard.edu/centos/7/isos/x86_64/CentOS-7-x86_64-Minimal-1503-01.iso", "iso_name": "CentOS-7-x86_64-Minimal-1503-01.iso", @@ -26,7 +28,8 @@ "vm_name": "packer-centos-7-x86_64-acs-minimal-template", "vm_memory": "8192", "vm_vcpus": 1, - "nfs_mount": "10.204.136.41:/vol/exports/packer" + "nfs_mount": "10.204.136.41:/vol/exports/packer", + "convert_to_template": false } ],