func getAmiMap(artifact packer.Artifact) map[string]string {

	meta := artifact.State("atlas.artifact.metadata")
	if meta == nil {
		log.Println("Artifact has no AWS info: artifact.State(atlas.artifact.metadata)")
		return nil
	}

	regionMap, ok := meta.(map[interface{}]interface{})
	if !ok {
		return nil
	}

	amiMap := make(map[string]string)
	for reg, ami := range regionMap {
		r, ok := reg.(string)
		if !ok {
			log.Printf("Couldnt convert Region to string: %#v \n", reg)
		}
		a, ok := ami.(string)
		if !ok {
			log.Printf("Couldnt convert Ami to string: %#v \n", ami)
		}
		r = strings.TrimPrefix(r, "region.")
		amiMap[r] = a
	}
	return amiMap
}
Beispiel #2
0
func (p *PostProcessor) artifactType(artifact packer.Artifact) string {
	if !p.config.TypeOverride {
		if v := artifact.State(ArtifactStateType); v != nil {
			return v.(string)
		}
	}

	return p.config.Type
}
Beispiel #3
0
func (p *PostProcessor) metadata(artifact packer.Artifact) map[string]string {
	var metadata map[string]string
	metadataRaw := artifact.State(ArtifactStateMetadata)
	if metadataRaw != nil {
		if err := mapstructure.Decode(metadataRaw, &metadata); err != nil {
			panic(err)
		}
	}

	if p.config.Metadata != nil {
		// If we have no extra metadata, just return as-is
		if metadata == nil {
			return p.config.Metadata
		}

		// Merge the metadata
		for k, v := range p.config.Metadata {
			metadata[k] = v
		}
	}

	return metadata
}
Beispiel #4
0
func (p *LibVirtProvider) Process(ui packer.Ui, artifact packer.Artifact, dir string) (vagrantfile string, metadata map[string]interface{}, err error) {
	diskName := artifact.State("diskName").(string)

	// Copy the disk image into the temporary directory (as box.img)
	for _, path := range artifact.Files() {
		if strings.HasSuffix(path, "/"+diskName) {
			ui.Message(fmt.Sprintf("Copying from artifact: %s", path))
			dstPath := filepath.Join(dir, "box.img")
			if err = CopyContents(dstPath, path); err != nil {
				return
			}
		}
	}

	format := artifact.State("diskType").(string)
	origSize := artifact.State("diskSize").(uint64)
	size := origSize / 1024 // In MB, want GB
	if origSize%1024 > 0 {
		// Make sure we don't make the size smaller
		size++
	}
	domainType := artifact.State("domainType").(string)

	// Convert domain type to libvirt driver
	var driver string
	switch domainType {
	case "none", "tcg":
		driver = "qemu"
	case "kvm":
		driver = domainType
	default:
		return "", nil, fmt.Errorf("Unknown libvirt domain type: %s", domainType)
	}

	// Create the metadata
	metadata = map[string]interface{}{
		"provider":     "libvirt",
		"format":       format,
		"virtual_size": size,
	}

	vagrantfile = fmt.Sprintf(libvirtVagrantfile, driver)
	return
}
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
	ui.Say("Starting googlecompute-export...")
	ui.Say(fmt.Sprintf("Exporting image to destinations: %v", p.config.Paths))
	if artifact.BuilderId() != googlecompute.BuilderId {
		err := fmt.Errorf(
			"Unknown artifact type: %s\nCan only export from Google Compute Engine builder artifacts.",
			artifact.BuilderId())
		return nil, p.config.KeepOriginalImage, err
	}

	result := &Artifact{paths: p.config.Paths}

	if len(p.config.Paths) > 0 {
		accountKeyFilePath := artifact.State("AccountFilePath").(string)
		imageName := artifact.State("ImageName").(string)
		imageSizeGb := artifact.State("ImageSizeGb").(int64)
		projectId := artifact.State("ProjectId").(string)
		zone := artifact.State("BuildZone").(string)

		// Set up instance configuration.
		instanceName := fmt.Sprintf("%s-exporter", artifact.Id())
		metadata := map[string]string{
			"image_name":     imageName,
			"name":           instanceName,
			"paths":          strings.Join(p.config.Paths, " "),
			"startup-script": StartupScript,
			"zone":           zone,
		}
		exporterConfig := googlecompute.Config{
			InstanceName:         instanceName,
			SourceImageProjectId: "debian-cloud",
			SourceImage:          "debian-8-jessie-v20160629",
			DiskName:             instanceName,
			DiskSizeGb:           imageSizeGb + 10,
			DiskType:             "pd-standard",
			Metadata:             metadata,
			MachineType:          "n1-standard-4",
			Zone:                 zone,
			Network:              "default",
			RawStateTimeout:      "5m",
		}
		exporterConfig.CalcTimeout()

		// Set up credentials and GCE driver.
		b, err := ioutil.ReadFile(accountKeyFilePath)
		if err != nil {
			err = fmt.Errorf("Error fetching account credentials: %s", err)
			return nil, p.config.KeepOriginalImage, err
		}
		accountKeyContents := string(b)
		googlecompute.ProcessAccountFile(&exporterConfig.Account, accountKeyContents)
		driver, err := googlecompute.NewDriverGCE(ui, projectId, &exporterConfig.Account)
		if err != nil {
			return nil, p.config.KeepOriginalImage, err
		}

		// Set up the state.
		state := new(multistep.BasicStateBag)
		state.Put("config", &exporterConfig)
		state.Put("driver", driver)
		state.Put("ui", ui)

		// Build the steps.
		steps := []multistep.Step{
			&googlecompute.StepCreateSSHKey{
				Debug:        p.config.PackerDebug,
				DebugKeyPath: fmt.Sprintf("gce_%s.pem", p.config.PackerBuildName),
			},
			&googlecompute.StepCreateInstance{
				Debug: p.config.PackerDebug,
			},
			new(googlecompute.StepWaitInstanceStartup),
			new(googlecompute.StepTeardownInstance),
		}

		// Run the steps.
		if p.config.PackerDebug {
			p.runner = &multistep.DebugRunner{
				Steps:   steps,
				PauseFn: common.MultistepDebugFn(ui),
			}
		} else {
			p.runner = &multistep.BasicRunner{Steps: steps}
		}
		p.runner.Run(state)
	}

	return result, p.config.KeepOriginalImage, nil
}
Beispiel #6
0
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
	if _, ok := builtins[artifact.BuilderId()]; !ok {
		return nil, false, fmt.Errorf("Unknown artifact type, can't process artifact: %s", artifact.BuilderId())
	}

	vhd := ""
	for _, path := range artifact.Files() {
		if strings.HasSuffix(path, ".vhd") {
			vhd = path
			break
		}
	}

	if vhd == "" {
		return nil, false, fmt.Errorf("No VHD artifact file found")
	}

	vmType := artifact.State("virtualizationType")
	if vhd == "" {
		return nil, false, fmt.Errorf("Virtualization type wasn't specified")
	}

	requiresHVM := "false"
	if strings.ToLower(vmType.(string)) == "hvm" {
		requiresHVM = "true"
	}

	dir, file := path.Split(vhd)

	copyFromUrl := ""
	uploadFile := vhd

	if p.config.CompressVhd {
		uploadFile = dir + "template.vhd.gzip"
		os.Remove(uploadFile) // remove any existing file to ensure no corruption

		ui.Message(fmt.Sprintf("Compressing '%s' to '%s'", vhd, uploadFile))

		err := compressVhd(vhd, uploadFile)
		if err != nil {
			return nil, false, fmt.Errorf("Error compressing template '%s': %s", vhd, err)
		}

		if strings.HasSuffix(p.config.DownloadUrl, "/") {
			copyFromUrl = p.config.DownloadUrl + "template.vhd.gzip"
		} else {
			copyFromUrl = fmt.Sprintf("%s/%s", p.config.DownloadUrl, "template.vhd.gzip")
		}
	} else {
		if strings.HasSuffix(p.config.DownloadUrl, "/") {
			copyFromUrl = p.config.DownloadUrl + file
		} else {
			copyFromUrl = fmt.Sprintf("%s/%s", p.config.DownloadUrl, file)
		}
	}

	ui.Message(fmt.Sprintf("Uploading %s to CloudStack", uploadFile))

	// Create a new caching client
	acs, err := gocs.NewCachingClient(p.config.ApiUrl, p.config.ApiKey, p.config.Secret, 0, false)
	if err != nil {
		return nil, false, fmt.Errorf("Connection error: %s", err)
	}

	ostypeid, err := acs.Request("listOsTypes", fmt.Sprintf("description:%s", p.config.OsType))
	if err != nil {
		return nil, false, fmt.Errorf("Error locating OS type '%s': %s", p.config.OsType, err)
	}

	ui.Say(fmt.Sprintf("OS '%s' has id '%s'", p.config.OsType, ostypeid))

	zoneid, err := acs.Request("listZones", fmt.Sprintf("name:%s", p.config.Zone))
	if err != nil {
		return nil, false, fmt.Errorf("Error locating Zone '%s': %s", p.config.Zone, err)
	}

	ui.Say(fmt.Sprintf("Zone '%s' has id '%s'", p.config.Zone, zoneid))

	templateid, err := acs.Request("registerTemplate", fmt.Sprintf("displaytext:%s, ostypeid:%s, format:vhd, hypervisor:xenserver, name:%s, zoneid:%s, url:%s, requireshvm:%t, passwordenabled:%t, sshkeyenabled:%t, isdynamicallyscalable:%t",
		p.config.DisplayText, ostypeid, p.config.TemplateName, zoneid, copyFromUrl, requiresHVM, p.config.PwdEnabled, p.config.SshEnabled, p.config.HasTools))
	if err != nil {
		return nil, false, fmt.Errorf("Error registering template '%s': %s", p.config.TemplateName, err)
	}

	ui.Say(fmt.Sprintf("Template registered as '%s'", templateid))

	lastStatus := ""
	downloadStarted := false

	iterations := int(p.config.UploadTimer) / 5

	for i := 0; i < iterations; i++ {
		templateDetails, err := acs.RawRequest("listTemplates", fmt.Sprintf("id:%s, templatefilter:all", templateid))
		if err != nil {
			return nil, false, fmt.Errorf("Error locating template '%s': %s", templateid, err)
		}

		jsonResponse, err := gocs.UnmarshalResponse("template", templateDetails)
		if err != nil {
			return nil, false, fmt.Errorf("Error unmarshalling template repsonse: %s", err)
		}

		// a normal download will see the "status" start blank, then become non-blank in a few seconds, ending with isready:true
		// anything else is an error

		var status []TemplateResponse
		if err := json.Unmarshal(jsonResponse, &status); err != nil {
			return nil, false, fmt.Errorf("Error unmarshalling template repsonse: %s", err)
		}

		if status[0].Status != lastStatus {
			ui.Say(fmt.Sprintf("Template processing status '%s'", status[0].Status))
			lastStatus = status[0].Status
			if strings.TrimSpace(lastStatus) != "" && !downloadStarted {
				if strings.Contains(lastStatus, "%") {
					downloadStarted = true
				} else if strings.HasPrefix(lastStatus, "Failed") {
					return nil, false, fmt.Errorf("Template '%s' processing aborted due to error: '%s'", p.config.TemplateName, strings.TrimSpace(lastStatus))
				} else {
					return nil, false, fmt.Errorf("Template '%s' download aborted due to error: '%s'", p.config.TemplateName, strings.TrimSpace(lastStatus))
				}
			}
		}

		if status[0].IsReady {
			ui.Say(fmt.Sprintf("Template '%s' is ready ", p.config.TemplateName))
			break
		}

		time.Sleep(time.Duration(5) * time.Second)
	}

	return artifact, false, nil
}
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact /*keep*/, bool, error) {
	ui.Say("Validating artifact")
	if artifact.BuilderId() != azure.BuilderId {
		return nil, false, fmt.Errorf(
			"Unknown artifact type: %s\nCan only import from Azure builder artifacts (%s).",
			artifact.BuilderId(), azure.BuilderId)
	}

	publishSettingsPath, ok := artifact.State("publishSettingsPath").(string)
	if !ok || publishSettingsPath == "" {
		return nil, false, fmt.Errorf(stateError, "publishSettingsPath")
	}
	subscriptionID, ok := artifact.State("subscriptionID").(string)
	if !ok || subscriptionID == "" {
		return nil, false, fmt.Errorf(stateError, "subscriptionID")
	}

	name := artifact.Id()

	ui.Message("Creating Azure Service Management client...")
	client, err := management.ClientFromPublishSettingsFile(publishSettingsPath, subscriptionID)
	if err != nil {
		return nil, false, fmt.Errorf("Error creating new Azure client: %v", err)
	}
	client = azure.GetLoggedClient(client)
	vmic := virtualmachineimage.NewClient(client)

	ui.Message("Retrieving VM image...")
	var image virtualmachineimage.VMImage
	if err = retry.ExecuteOperation(func() error {
		imageList, err := vmic.ListVirtualMachineImages(
			virtualmachineimage.ListParameters{
				Category: virtualmachineimage.CategoryUser,
			})
		if err != nil {
			return err
		}

		for _, i := range imageList.VMImages {
			if i.Name == name {
				image = i
				break
			}
		}
		return nil
	}); err != nil {
		log.Printf("VM image client returned error: %s", err)
		return nil, false, err
	}
	if image.Name != name {
		return nil, false, fmt.Errorf("Could not find image: %s", name)
	}

	ui.Message(fmt.Sprintf("Deleting VM image (keeping VHDs) %s: %s...", image.Name, image.Label))
	err = retry.ExecuteOperation(func() error { return vmic.DeleteVirtualMachineImage(image.Name, false) })
	if err != nil {
		log.Printf("Error deleting VM image: %s", err)
		return nil, false, err
	}

	blobs := VMBlobListArtifact{
		OSDisk:    image.OSDiskConfiguration.MediaLink,
		DataDisks: make([]string, len(image.DataDiskConfigurations))}

	for i, ddc := range image.DataDiskConfigurations {
		blobs.DataDisks[i] = ddc.MediaLink
	}

	return blobs, false, nil
}