func (s *StepAMIRegionCopy) Run(state multistep.StateBag) multistep.StepAction { ec2conn := state.Get("ec2").(*ec2.EC2) ui := state.Get("ui").(packer.Ui) amis := state.Get("amis").(map[string]string) snapshots := state.Get("snapshots").(map[string][]string) ami := amis[*ec2conn.Config.Region] if len(s.Regions) == 0 { return multistep.ActionContinue } ui.Say(fmt.Sprintf("Copying AMI (%s) to other regions...", ami)) var lock sync.Mutex var wg sync.WaitGroup errs := new(packer.MultiError) for _, region := range s.Regions { if region == *ec2conn.Config.Region { ui.Message(fmt.Sprintf( "Avoiding copying AMI to duplicate region %s", region)) continue } wg.Add(1) ui.Message(fmt.Sprintf("Copying to: %s", region)) go func(region string) { defer wg.Done() id, snapshotIds, err := amiRegionCopy(state, s.AccessConfig, s.Name, ami, region, *ec2conn.Config.Region) lock.Lock() defer lock.Unlock() amis[region] = id snapshots[region] = snapshotIds if err != nil { errs = packer.MultiErrorAppend(errs, err) } }(region) } // TODO(mitchellh): Wait but also allow for cancels to go through... ui.Message("Waiting for all copies to complete...") wg.Wait() // If there were errors, show them if len(errs.Errors) > 0 { state.Put("error", errs) ui.Error(errs.Error()) return multistep.ActionHalt } state.Put("amis", amis) return multistep.ActionContinue }
func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error) { var errs *packer.MultiError err := hconfig.Decode(&self.config, &hconfig.DecodeOpts{ Interpolate: true, InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "boot_command", }, }, }, raws...) if err != nil { packer.MultiErrorAppend(errs, err) } errs = packer.MultiErrorAppend( errs, self.config.CommonConfig.Prepare(&self.config.ctx, &self.config.PackerConfig)...) // Set default values if self.config.VMMemory == 0 { self.config.VMMemory = 1024 } if len(self.config.PlatformArgs) == 0 { pargs := make(map[string]string) pargs["viridian"] = "false" pargs["nx"] = "true" pargs["pae"] = "true" pargs["apic"] = "true" pargs["timeoffset"] = "0" pargs["acpi"] = "1" self.config.PlatformArgs = pargs } // Validation if self.config.SourcePath == "" { errs = packer.MultiErrorAppend(errs, fmt.Errorf("A source_path must be specified")) } if len(errs.Errors) > 0 { retErr = errors.New(errs.Error()) } return nil, retErr }
func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error) { var errs *packer.MultiError err := hconfig.Decode(&self.config, &hconfig.DecodeOpts{ Interpolate: true, InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "boot_command", }, }, }, raws...) if err != nil { packer.MultiErrorAppend(errs, err) } errs = packer.MultiErrorAppend( errs, self.config.CommonConfig.Prepare(&self.config.ctx, &self.config.PackerConfig)...) errs = packer.MultiErrorAppend(errs, self.config.SSHConfig.Prepare(&self.config.ctx)...) // Set default values if self.config.RawBootTimeout == "" { self.config.RawBootTimeout = "200m" } // Validation self.config.BootTimeout, err = time.ParseDuration(self.config.RawBootTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse boot_timeout: %s", err)) } self.config.TemporaryVm = self.config.VMName + "_packer_snap" if len(errs.Errors) > 0 { retErr = errors.New(errs.Error()) } return nil, retErr }
// Prepare processes the build configuration parameters. func (self *Builder) Prepare(raws ...interface{}) (parms []string, retErr error) { err := config.Decode(&self.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &self.config.ctx, }, raws...) if err != nil { return nil, err } // Assign default values if possible if self.config.APIKey == "" { // Default to environment variable for api_key, if it exists self.config.APIKey = os.Getenv("SOFTLAYER_API_KEY") } if self.config.Username == "" { // Default to environment variable for client_id, if it exists self.config.Username = os.Getenv("SOFTLAYER_USER_NAME") } if self.config.DatacenterName == "" { self.config.DatacenterName = "ams01" } if self.config.InstanceName == "" { self.config.InstanceName = fmt.Sprintf("packer-softlayer-%s", time.Now().Unix()) } if self.config.InstanceDomain == "" { self.config.InstanceDomain = "defaultdomain.com" } if self.config.ImageDescription == "" { self.config.ImageDescription = "Instance snapshot. Generated by packer.io" } if self.config.ImageType == "" { self.config.ImageType = IMAGE_TYPE_FLEX } if self.config.InstanceCpu == 0 { self.config.InstanceCpu = 1 } if self.config.InstanceMemory == 0 { self.config.InstanceMemory = 1024 } if self.config.InstanceNetworkSpeed == 0 { self.config.InstanceNetworkSpeed = 10 } if self.config.InstanceDiskCapacity == 0 { self.config.InstanceDiskCapacity = 25 } if self.config.Comm.SSHUsername == "" { self.config.Comm.SSHUsername = "******" } if self.config.RawStateTimeout == "" { self.config.RawStateTimeout = "10m" } // Validation var errs *packer.MultiError errs = packer.MultiErrorAppend(errs, self.config.Comm.Prepare(&self.config.ctx)...) // Check for required configurations that will display errors if not set if self.config.APIKey == "" { errs = packer.MultiErrorAppend( errs, errors.New("api_key or the SOFTLAYER_API_KEY environment variable must be specified")) } if self.config.Username == "" { errs = packer.MultiErrorAppend( errs, errors.New("username or the SOFTLAYER_USER_NAME environment variable must be specified")) } if self.config.ImageName == "" { errs = packer.MultiErrorAppend( errs, errors.New("image_name must be specified")) } if self.config.ImageType != IMAGE_TYPE_FLEX && self.config.ImageType != IMAGE_TYPE_STANDARD { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unknown image_type '%s'. Must be one of 'flex' (the default) or 'standard'.", self.config.ImageType)) } if self.config.BaseImageId == "" && self.config.BaseOsCode == "" { errs = packer.MultiErrorAppend( errs, errors.New("please specify base_image_id or base_os_code")) } if self.config.BaseImageId != "" && self.config.BaseOsCode != "" { errs = packer.MultiErrorAppend( errs, errors.New("please specify only one of base_image_id or base_os_code")) } if self.config.BaseImageId != "" && self.config.Comm.SSHPrivateKey == "" { errs = packer.MultiErrorAppend( errs, errors.New("when using base_image_id, you must specify ssh_private_key_file "+ "since automatic ssh key config for custom images isn't supported by SoftLayer API")) } stateTimeout, err := time.ParseDuration(self.config.RawStateTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed parsing state_timeout: %s", err)) } self.config.StateTimeout = stateTimeout log.Println(common.ScrubConfig(self.config, self.config.APIKey, self.config.Username)) if len(errs.Errors) > 0 { retErr = errors.New(errs.Error()) } return nil, retErr }
func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error) { var errs *packer.MultiError err := hconfig.Decode(&self.config, &hconfig.DecodeOpts{ Interpolate: true, InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "boot_command", }, }, }, raws...) if err != nil { packer.MultiErrorAppend(errs, err) } errs = packer.MultiErrorAppend( errs, self.config.CommonConfig.Prepare(&self.config.ctx, &self.config.PackerConfig)...) errs = packer.MultiErrorAppend(errs, self.config.SSHConfig.Prepare(&self.config.ctx)...) // Set default values if self.config.RawInstallTimeout == "" { self.config.RawInstallTimeout = "200m" } if self.config.DiskSize == 0 { self.config.DiskSize = 40000 } if self.config.VMMemory == 0 { self.config.VMMemory = 1024 } if self.config.CloneTemplate == "" { self.config.CloneTemplate = "Other install media" } if len(self.config.PlatformArgs) == 0 { pargs := make(map[string]string) pargs["viridian"] = "false" pargs["nx"] = "true" pargs["pae"] = "true" pargs["apic"] = "true" pargs["timeoffset"] = "0" pargs["acpi"] = "1" self.config.PlatformArgs = pargs } // Template substitution templates := map[string]*string{ "clone_template": &self.config.CloneTemplate, "network_name": &self.config.NetworkName, "iso_checksum": &self.config.ISOChecksum, "iso_checksum_type": &self.config.ISOChecksumType, "iso_url": &self.config.ISOUrl, "iso_name": &self.config.ISOName, "install_timeout": &self.config.RawInstallTimeout, } for i := range self.config.ISOUrls { templates[fmt.Sprintf("iso_urls[%d]", i)] = &self.config.ISOUrls[i] } // Validation self.config.InstallTimeout, err = time.ParseDuration(self.config.RawInstallTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse install_timeout: %s", err)) } if self.config.ISOName == "" { // If ISO name is not specified, assume a URL and checksum has been provided. if self.config.ISOChecksumType == "" { errs = packer.MultiErrorAppend( errs, errors.New("The iso_checksum_type must be specified.")) } else { self.config.ISOChecksumType = strings.ToLower(self.config.ISOChecksumType) if self.config.ISOChecksumType != "none" { if self.config.ISOChecksum == "" { errs = packer.MultiErrorAppend( errs, errors.New("Due to the file size being large, an iso_checksum is required.")) } else { self.config.ISOChecksum = strings.ToLower(self.config.ISOChecksum) } if hash := common.HashForType(self.config.ISOChecksumType); hash == nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Unsupported checksum type: %s", self.config.ISOChecksumType)) } } } if len(self.config.ISOUrls) == 0 { if self.config.ISOUrl == "" { errs = packer.MultiErrorAppend( errs, errors.New("One of iso_url or iso_urls must be specified.")) } else { self.config.ISOUrls = []string{self.config.ISOUrl} } } else if self.config.ISOUrl != "" { errs = packer.MultiErrorAppend( errs, errors.New("Only one of iso_url or iso_urls may be specified.")) } for i, url := range self.config.ISOUrls { self.config.ISOUrls[i], err = common.DownloadableURL(url) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse iso_urls[%d]: %s", i, err)) } } } else { // An ISO name has been provided. It should be attached from an available SR. } if len(errs.Errors) > 0 { retErr = errors.New(errs.Error()) } return nil, retErr }
func (self *Builder) Prepare(raws ...interface{}) (params []string, retErr error) { var errs *packer.MultiError err := hconfig.Decode(&self.config, &hconfig.DecodeOpts{ Interpolate: true, InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "boot_command", }, }, }, raws...) if err != nil { packer.MultiErrorAppend(errs, err) } errs = packer.MultiErrorAppend( errs, self.config.CommonConfig.Prepare(&self.config.ctx, &self.config.PackerConfig)...) errs = packer.MultiErrorAppend(errs, self.config.SSHConfig.Prepare(&self.config.ctx)...) // Set default values if self.config.RawInstallTimeout == "" { self.config.RawInstallTimeout = "200m" } if self.config.DiskSize == 0 { self.config.DiskSize = 40000 } if self.config.VMMemory == 0 { self.config.VMMemory = 1024 } if self.config.VMVCpus == 0 { self.config.VMVCpus = 1 } if self.config.CloneTemplate == "" { self.config.CloneTemplate = "Other install media" } if len(self.config.PlatformArgs) == 0 { pargs := make(map[string]string) pargs["viridian"] = "false" pargs["nx"] = "true" pargs["pae"] = "true" pargs["apic"] = "true" pargs["timeoffset"] = "0" pargs["acpi"] = "1" pargs["cores_per_socket"] = "1" self.config.PlatformArgs = pargs } // Template and environment substitution /* templates := map[string]*string{ "clone_template": &self.config.CloneTemplate, "network_name": &self.config.NetworkName, "iso_name": &self.config.ISOName, "iso_url": &self.config.ISOUrl, "install_timeout": &self.config.RawInstallTimeout, } */ // Validation self.config.InstallTimeout, err = time.ParseDuration(self.config.RawInstallTimeout) if err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("Failed to parse install_timeout: %s", err)) } if self.config.ISOName == "" { errs = packer.MultiErrorAppend( errs, errors.New("You must specify the ISO name")) } if self.config.ISOUrl != "" { if self.config.ScriptUrl == "" { errs = packer.MultiErrorAppend( errs, errors.New("You must specify the URL of the copyiso script")) } if self.config.ISOSRName == "" { errs = packer.MultiErrorAppend( errs, errors.New("You must specify the SR for the ISO")) } } if len(errs.Errors) > 0 { retErr = errors.New(errs.Error()) } return nil, retErr }
func (s *stepPrepareConfig) Run(state multistep.StateBag) multistep.StepAction { client := state.Get("client").(*cloudstack.CloudStackClient) config := state.Get("config").(*Config) ui := state.Get("ui").(packer.Ui) ui.Say("Preparing config...") var err error var errs *packer.MultiError // First get the project and zone UUID's so we can use them in other calls when needed. if config.Project != "" && !isUUID(config.Project) { config.Project, _, err = client.Project.GetProjectID(config.Project) if err != nil { errs = packer.MultiErrorAppend(errs, &retrieveErr{"project", config.Project, err}) } } if config.UserDataFile != "" { userdata, err := ioutil.ReadFile(config.UserDataFile) if err != nil { errs = packer.MultiErrorAppend(errs, fmt.Errorf("problem reading user data file: %s", err)) } config.UserData = string(userdata) } if !isUUID(config.Zone) { config.Zone, _, err = client.Zone.GetZoneID(config.Zone) if err != nil { errs = packer.MultiErrorAppend(errs, &retrieveErr{"zone", config.Zone, err}) } } // Then try to get the remaining UUID's. if config.DiskOffering != "" && !isUUID(config.DiskOffering) { config.DiskOffering, _, err = client.DiskOffering.GetDiskOfferingID(config.DiskOffering) if err != nil { errs = packer.MultiErrorAppend(errs, &retrieveErr{"disk offering", config.DiskOffering, err}) } } if config.PublicIPAddress != "" && !isUUID(config.PublicIPAddress) { // Save the public IP address before replacing it with it's UUID. config.hostAddress = config.PublicIPAddress p := client.Address.NewListPublicIpAddressesParams() p.SetIpaddress(config.PublicIPAddress) if config.Project != "" { p.SetProjectid(config.Project) } ipAddrs, err := client.Address.ListPublicIpAddresses(p) if err != nil { errs = packer.MultiErrorAppend(errs, &retrieveErr{"IP address", config.PublicIPAddress, err}) } if err == nil && ipAddrs.Count != 1 { errs = packer.MultiErrorAppend(errs, &retrieveErr{"IP address", config.PublicIPAddress, ipAddrs}) } if err == nil && ipAddrs.Count == 1 { config.PublicIPAddress = ipAddrs.PublicIpAddresses[0].Id } } if !isUUID(config.Network) { config.Network, _, err = client.Network.GetNetworkID(config.Network, cloudstack.WithProject(config.Project)) if err != nil { errs = packer.MultiErrorAppend(errs, &retrieveErr{"network", config.Network, err}) } } if !isUUID(config.ServiceOffering) { config.ServiceOffering, _, err = client.ServiceOffering.GetServiceOfferingID(config.ServiceOffering) if err != nil { errs = packer.MultiErrorAppend(errs, &retrieveErr{"service offering", config.ServiceOffering, err}) } } if config.SourceISO != "" { if isUUID(config.SourceISO) { config.instanceSource = config.SourceISO } else { config.instanceSource, _, err = client.ISO.GetIsoID(config.SourceISO, "executable", config.Zone) if err != nil { errs = packer.MultiErrorAppend(errs, &retrieveErr{"ISO", config.SourceISO, err}) } } } if config.SourceTemplate != "" { if isUUID(config.SourceTemplate) { config.instanceSource = config.SourceTemplate } else { config.instanceSource, _, err = client.Template.GetTemplateID(config.SourceTemplate, "executable", config.Zone) if err != nil { errs = packer.MultiErrorAppend(errs, &retrieveErr{"template", config.SourceTemplate, err}) } } } if !isUUID(config.TemplateOS) { p := client.GuestOS.NewListOsTypesParams() p.SetDescription(config.TemplateOS) types, err := client.GuestOS.ListOsTypes(p) if err != nil { errs = packer.MultiErrorAppend(errs, &retrieveErr{"OS type", config.TemplateOS, err}) } if err == nil && types.Count != 1 { errs = packer.MultiErrorAppend(errs, &retrieveErr{"OS type", config.TemplateOS, types}) } if err == nil && types.Count == 1 { config.TemplateOS = types.OsTypes[0].Id } } // This is needed because nil is not always nil. When returning *packer.MultiError(nil) // as an error interface, that interface will no longer be equal to nil but it will be // an interface with type *packer.MultiError and value nil which is different then a // nil interface. if errs != nil && len(errs.Errors) > 0 { ui.Error(errs.Error()) return multistep.ActionHalt } ui.Message("Config has been prepared!") return multistep.ActionContinue }