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

}
Beispiel #3
0
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

}
Beispiel #6
0
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
}