func GetVMImage( t *testing.T, client management.Client, filter func(vmimage.VMImage) bool) vmimage.VMImage { t.Log("Selecting VM image") allimages, err := vmimage.NewClient(client).ListVirtualMachineImages(vmimage.ListParameters{}) if err != nil { t.Fatal(err) } filtered := []vmimage.VMImage{} for _, im := range allimages.VMImages { if filter(im) { filtered = append(filtered, im) } } if len(filtered) == 0 { t.Fatal("Filter too restrictive, no images left?") } image := filtered[0] for _, im := range filtered { if im.PublishedDate > image.PublishedDate { image = im } } t.Logf("Selecting image '%s'", image.Name) return image }
func (s *StepCreateImage) Run(state multistep.StateBag) multistep.StepAction { client := state.Get(constants.RequestManager).(management.Client) ui := state.Get(constants.Ui).(packer.Ui) errorMsg := "Error Creating Azure Image: %s" ui.Say("Creating Azure Image. If Successful, This Will Remove the Temporary VM...") description := "packer made image" imageFamily := "PackerMade" if err := retry.ExecuteAsyncOperation(client, func() (management.OperationID, error) { return vmi.NewClient(client).Capture(s.TmpServiceName, s.TmpVmName, s.TmpVmName, s.UserImageName, s.UserImageLabel, vmi.OSStateGeneralized, vmi.CaptureParameters{ Description: description, ImageFamily: imageFamily, RecommendedVMSize: s.RecommendedVMSize, }) }); err != nil { err := fmt.Errorf(errorMsg, err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } // CatpureVMImage removes the VM state.Put(constants.ImageCreated, 1) state.Put(constants.VmExists, 0) return multistep.ActionContinue }
// NewClientFromSettingsFile returns a new Azure management // client created using a publish settings file. func (c *Config) NewClientFromSettingsFile() (*Client, error) { if _, err := os.Stat(c.SettingsFile); os.IsNotExist(err) { return nil, fmt.Errorf("Publish Settings file %q does not exist!", c.SettingsFile) } mc, err := management.ClientFromPublishSettingsFile(c.SettingsFile, c.SubscriptionID) if err != nil { return nil, nil } return &Client{ mgmtClient: mc, affinityGroupClient: affinitygroup.NewClient(mc), hostedServiceClient: hostedservice.NewClient(mc), secGroupClient: networksecuritygroup.NewClient(mc), osImageClient: osimage.NewClient(mc), sqlClient: sql.NewClient(mc), storageServiceClient: storageservice.NewClient(mc), vmClient: virtualmachine.NewClient(mc), vmDiskClient: virtualmachinedisk.NewClient(mc), vmImageClient: virtualmachineimage.NewClient(mc), vnetClient: virtualnetwork.NewClient(mc), mutex: &sync.Mutex{}, }, nil }
func TestVMImageList(t *testing.T) { client := testutils.GetTestClient(t) vmic := vmimage.NewClient(client) il, _ := vmic.ListVirtualMachineImages(vmimage.ListParameters{}) for _, im := range il.VMImages { t.Logf("%s -%s", im.Name, im.Description) } }
func (b *Builder) validateAzureOptions(ui packer.Ui, state *multistep.BasicStateBag) error { var err error // Check Storage account (& container) ui.Message("Checking Storage Account...") availabilityResponse, err := storageservice.NewClient(b.client).CheckStorageAccountNameAvailability(b.config.StorageAccount) if err != nil { return err } if availabilityResponse.Result { return fmt.Errorf("Can't Find Storage Account '%s'", b.config.StorageAccount) } // Check image exists imageList, err := osimage.NewClient(b.client).ListOSImages() if err != nil { log.Printf("OS image client returned error: %s", err) return err } if osImage, found := FindOSImage(imageList.OSImages, b.config.OSImageLabel, b.config.Location); found { state.Put(constants.OSImageName, osImage.Name) state.Put(constants.IsOSImage, true) return nil } else { imageList, err := vmimage.NewClient(b.client).ListVirtualMachineImages() if err != nil { log.Printf("VM image client returned error: %s", err) return err } if vmImage, found := FindVmImage(imageList.VMImages, "", b.config.OSImageLabel, b.config.Location); found { state.Put(constants.OSImageName, vmImage.Name) state.Put(constants.IsOSImage, false) return nil } else { return fmt.Errorf("Can't find VM or OS image '%s' Located at '%s'", b.config.OSImageLabel, b.config.Location) } } }
func (c *Config) NewClientFromSettingsData() (*Client, error) { mc, err := management.ClientFromPublishSettingsData(c.Settings, c.SubscriptionID) if err != nil { return nil, nil } return &Client{ mgmtClient: mc, affinityGroupClient: affinitygroup.NewClient(mc), hostedServiceClient: hostedservice.NewClient(mc), secGroupClient: networksecuritygroup.NewClient(mc), osImageClient: osimage.NewClient(mc), sqlClient: sql.NewClient(mc), storageServiceClient: storageservice.NewClient(mc), vmClient: virtualmachine.NewClient(mc), vmDiskClient: virtualmachinedisk.NewClient(mc), vmImageClient: virtualmachineimage.NewClient(mc), vnetClient: virtualnetwork.NewClient(mc), mutex: &sync.Mutex{}, }, nil }
// Run executes a Packer build and returns a packer.Artifact representing // a Azure VM image. func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { ui.Say("Preparing builder...") ui.Message("Creating Azure Service Management client...") subscriptionID, err := findSubscriptionID(b.config.PublishSettingsPath, b.config.SubscriptionName) if err != nil { return nil, fmt.Errorf("Error creating new Azure client: %v", err) } b.client, err = management.ClientFromPublishSettingsFile(b.config.PublishSettingsPath, subscriptionID) if err != nil { return nil, fmt.Errorf("Error creating new Azure client: %v", err) } // add logger if appropriate b.client = GetLoggedClient(b.client) // Set up the state. state := new(multistep.BasicStateBag) state.Put(constants.Config, b.config) state.Put(constants.RequestManager, b.client) state.Put("hook", hook) state.Put(constants.Ui, ui) // complete flags state.Put(constants.SrvExists, 0) state.Put(constants.CertInstalled, 0) state.Put(constants.CertUploaded, 0) state.Put(constants.VmExists, 0) state.Put(constants.DiskExists, 0) state.Put(constants.VmRunning, 0) state.Put(constants.ImageCreated, 0) var steps []multistep.Step if b.config.OSType == constants.Target_Linux { steps = []multistep.Step{ &lin.StepCreateCert{ TmpServiceName: b.config.tmpServiceName, }, new(StepValidate), &StepCreateService{ Location: b.config.Location, TmpServiceName: b.config.tmpServiceName, }, &StepUploadCertificate{ TmpServiceName: b.config.tmpServiceName, }, new(StepCreateVm), &StepPollStatus{ TmpServiceName: b.config.tmpServiceName, TmpVmName: b.config.tmpVmName, OSType: b.config.OSType, }, &communicator.StepConnectSSH{ Config: &b.config.Comm, Host: lin.SSHHost, SSHConfig: lin.SSHConfig(b.config.UserName), }, &common.StepProvision{}, &lin.StepGeneralizeOS{ Command: "sudo /usr/sbin/waagent -force -deprovision+user && export HISTSIZE=0 && sync", }, &StepStopVm{ TmpVmName: b.config.tmpVmName, TmpServiceName: b.config.tmpServiceName, }, &StepCreateImage{ TmpServiceName: b.config.tmpServiceName, TmpVmName: b.config.tmpVmName, UserImageName: b.config.userImageName, UserImageLabel: b.config.UserImageLabel, RecommendedVMSize: b.config.InstanceSize, }, } } else if b.config.OSType == constants.Target_Windows { steps = []multistep.Step{ new(StepValidate), &StepCreateService{ Location: b.config.Location, TmpServiceName: b.config.tmpServiceName, }, new(StepCreateVm), &StepPollStatus{ TmpServiceName: b.config.tmpServiceName, TmpVmName: b.config.tmpVmName, OSType: b.config.OSType, }, &win.StepSetProvisionInfrastructure{ VmName: b.config.tmpVmName, ServiceName: b.config.tmpServiceName, StorageAccountName: b.config.StorageAccount, TempContainerName: b.config.tmpContainerName, ProvisionTimeoutInMinutes: b.config.ProvisionTimeoutInMinutes, }, &common.StepProvision{}, &StepStopVm{ TmpVmName: b.config.tmpVmName, TmpServiceName: b.config.tmpServiceName, }, &StepCreateImage{ TmpServiceName: b.config.tmpServiceName, TmpVmName: b.config.tmpVmName, UserImageName: b.config.userImageName, UserImageLabel: b.config.UserImageLabel, RecommendedVMSize: b.config.InstanceSize, }, } } else { return nil, fmt.Errorf("Unkonwn OS type: %s", b.config.OSType) } // Run the steps. if b.config.PackerDebug { b.runner = &multistep.DebugRunner{ Steps: steps, PauseFn: common.MultistepDebugFn(ui), } } else { b.runner = &multistep.BasicRunner{Steps: steps} } b.runner.Run(state) // Report any errors. if rawErr, ok := state.GetOk("error"); ok { return nil, rawErr.(error) } // If we were interrupted or cancelled, then just exit. if _, ok := state.GetOk(multistep.StateCancelled); ok { return nil, errors.New("Build was cancelled.") } if _, ok := state.GetOk(multistep.StateHalted); ok { return nil, errors.New("Build was halted.") } vmImageList, err := vmimage.NewClient(b.client).ListVirtualMachineImages( vmimage.ListParameters{ Location: b.config.Location, }) if err != nil { log.Printf("VM image client returned error: %s", err) return nil, fmt.Errorf("Can't create artifact") } if userImage, found := FindVmImage(vmImageList.VMImages, b.config.userImageName, b.config.UserImageLabel); found { return &artifact{ imageLabel: userImage.Label, imageName: userImage.Name, mediaLocation: userImage.OSDiskConfiguration.MediaLink, publishSettingsPath: b.config.PublishSettingsPath, subscriptionID: subscriptionID, }, nil } else { log.Printf("could not find image %s", b.config.userImageName) return nil, fmt.Errorf("Can't create artifact") } }
func TestDeployPlatformVMImageCaptureRedeploy(t *testing.T) { client := testutils.GetTestClient(t) vmname := GenerateName() sa := GetTestStorageAccount(t, client) location := sa.StorageServiceProperties.Location role := NewVMConfiguration(vmname, "Standard_D3") ConfigureDeploymentFromPlatformImage(&role, GetLinuxTestImage(t, client).Name, fmt.Sprintf("http://%s.blob.core.windows.net/sdktest/%s.vhd", sa.ServiceName, vmname), GenerateName()) ConfigureForLinux(&role, "myvm", "azureuser", GeneratePassword()) ConfigureWithPublicSSH(&role) t.Logf("Deploying VM: %s", vmname) createRoleConfiguration(t, client, role, location) t.Logf("Wait for deployment to enter running state") vmc := vm.NewClient(client) status := vm.DeploymentStatusDeploying for status != vm.DeploymentStatusRunning { deployment, err := vmc.GetDeployment(vmname, vmname) if err != nil { t.Error(err) break } status = deployment.Status } t.Logf("Shutting down VM: %s", vmname) if err := Await(client, func() (management.OperationID, error) { return vmc.ShutdownRole(vmname, vmname, vmname, vm.PostShutdownActionStopped) }); err != nil { t.Error(err) } if err := WaitForDeploymentInstanceStatus(client, vmname, vmname, vm.InstanceStatusStoppedVM); err != nil { t.Fatal(err) } imagename := GenerateName() t.Logf("Capturing VMImage: %s", imagename) if err := Await(client, func() (management.OperationID, error) { return vmimage.NewClient(client).Capture(vmname, vmname, vmname, imagename, imagename, vmimage.OSStateGeneralized, vmimage.CaptureParameters{}) }); err != nil { t.Error(err) } im := GetUserVMImage(t, client, imagename) t.Logf("Found image: %+v", im) newvmname := GenerateName() role = NewVMConfiguration(newvmname, "Standard_D3") ConfigureDeploymentFromUserVMImage(&role, im.Name) ConfigureForLinux(&role, newvmname, "azureuser", GeneratePassword()) ConfigureWithPublicSSH(&role) t.Logf("Deploying new VM from freshly captured VM image: %s", newvmname) if err := Await(client, func() (management.OperationID, error) { return vmc.CreateDeployment(role, vmname, vm.CreateDeploymentOptions{}) }); err != nil { t.Error(err) } deleteHostedService(t, client, vmname) }
func (*StepValidate) Run(state multistep.StateBag) multistep.StepAction { client := state.Get(constants.RequestManager).(management.Client) ui := state.Get(constants.Ui).(packer.Ui) config := state.Get(constants.Config).(*Config) ui.Say("Validating Azure options...") role := vmutils.NewVMConfiguration(config.tmpVmName, config.InstanceSize) ui.Message("Checking Storage Account...") destinationVhd, err := validateStorageAccount(config, client) if err != nil { err = fmt.Errorf("Error checking storage account: %v", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } ui.Message(fmt.Sprintf("Destination VHD: %s", destinationVhd)) if err := func() error { if config.RemoteSourceImageLink != "" { ui.Message("Checking remote image source link...") response, err := http.DefaultClient.Head(config.RemoteSourceImageLink) if response != nil && response.Body != nil { defer response.Body.Close() } if err != nil { log.Printf("HTTP client returned error: %s", err) return fmt.Errorf("error checking remote image source link: %v", err) } if response.StatusCode != 200 { return fmt.Errorf("Unexpected status while retrieving remote image source at %s: %d %s", config.RemoteSourceImageLink, response.StatusCode, response.Status) } size := float64(response.ContentLength) / 1024 / 1024 / 1024 ui.Say(fmt.Sprintf("Remote image size: %.1f GiB", size)) vmutils.ConfigureDeploymentFromRemoteImage(&role, config.RemoteSourceImageLink, config.OSType, fmt.Sprintf("%s-OSDisk", config.tmpVmName), destinationVhd, "") if config.ResizeOSVhdGB != nil { if float64(*config.ResizeOSVhdGB) < size { return fmt.Errorf("new OS VHD size of %d GiB is smaller than current size of %.1f GiB", *config.ResizeOSVhdGB, size) } ui.Say(fmt.Sprintf("Remote image will be resized to %d GiB", *config.ResizeOSVhdGB)) role.OSVirtualHardDisk.ResizedSizeInGB = *config.ResizeOSVhdGB } } else { ui.Message("Checking image source...") imageList, err := osimage.NewClient(client).ListOSImages() if err != nil { log.Printf("OS image client returned error: %s", err) return err } if osImage, found := FindOSImage(imageList.OSImages, config.OSImageLabel, config.Location); found { vmutils.ConfigureDeploymentFromPlatformImage(&role, osImage.Name, destinationVhd, "") ui.Message(fmt.Sprintf("Image source is OS image %q", osImage.Name)) if osImage.OS != config.OSType { return fmt.Errorf("OS image type (%q) does not match config (%q)", osImage.OS, config.OSType) } if config.ResizeOSVhdGB != nil { if float64(*config.ResizeOSVhdGB) < osImage.LogicalSizeInGB { return fmt.Errorf("new OS VHD size of %d GiB is smaller than current size of %.1f GiB", *config.ResizeOSVhdGB, osImage.LogicalSizeInGB) } ui.Say(fmt.Sprintf("OS image will be resized to %d GiB", *config.ResizeOSVhdGB)) role.OSVirtualHardDisk.ResizedSizeInGB = *config.ResizeOSVhdGB } } else { imageList, err := vmimage.NewClient(client).ListVirtualMachineImages( vmimage.ListParameters{ Location: config.Location, }) if err != nil { log.Printf("VM image client returned error: %s", err) return err } if vmImage, found := FindVmImage(imageList.VMImages, "", config.OSImageLabel); found { if config.ResizeOSVhdGB != nil { return fmt.Errorf("Packer cannot resize VM images") } if vmImage.OSDiskConfiguration.OSState != vmimage.OSStateGeneralized { return fmt.Errorf("Packer can only use VM user images with a generalized OS so that it can be reprovisioned. The specified image OS is not in a generalized state.") } if vmImage.Category == vmimage.CategoryUser { //vmutils.ConfigureDeploymentFromUserVMImage(&role, vmImage.Name) role.VMImageName = vmImage.Name } else { vmutils.ConfigureDeploymentFromPublishedVMImage(&role, vmImage.Name, destinationVhd, true) } ui.Message(fmt.Sprintf("Image source is VM image %q", vmImage.Name)) if vmImage.OSDiskConfiguration.OS != config.OSType { return fmt.Errorf("VM image type (%q) does not match config (%q)", vmImage.OSDiskConfiguration.OS, config.OSType) } } else { return fmt.Errorf("Can't find VM or OS image '%s' Located at '%s'", config.OSImageLabel, config.Location) } } } return nil }(); err != nil { err = fmt.Errorf("Error determining deployment source: %v", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } if config.OSType == constants.Target_Linux { certThumbprint := state.Get(constants.Thumbprint).(string) if len(certThumbprint) == 0 { err := fmt.Errorf("Certificate Thumbprint is empty") state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } vmutils.ConfigureForLinux(&role, config.tmpVmName, config.UserName, "", certThumbprint) // disallowing password login is irreversible on some images, see https://github.com/Azure/packer-azure/issues/62 for i, _ := range role.ConfigurationSets { if role.ConfigurationSets[i].ConfigurationSetType == vm.ConfigurationSetTypeLinuxProvisioning { role.ConfigurationSets[i].DisableSSHPasswordAuthentication = "false" } } vmutils.ConfigureWithPublicSSH(&role) } else if config.OSType == constants.Target_Windows { password := common.RandomPassword() state.Put("password", password) vmutils.ConfigureForWindows(&role, config.tmpVmName, config.UserName, password, true, "") vmutils.ConfigureWithPublicRDP(&role) vmutils.ConfigureWithPublicPowerShell(&role) } if config.VNet != "" && config.Subnet != "" { ui.Message("Checking VNet...") if err := checkVirtualNetworkConfiguration(client, config.VNet, config.Subnet, config.Location); err != nil { state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } vmutils.ConfigureWithSubnet(&role, config.Subnet) } for n, d := range config.DataDisks { switch d := d.(type) { case int: ui.Message(fmt.Sprintf("Configuring datadisk %d: new disk with size %d GB...", n, d)) destination := fmt.Sprintf("%s-data-%d.vhd", destinationVhd[:len(destinationVhd)-4], n) ui.Message(fmt.Sprintf("Destination VHD for data disk %s: %d", destinationVhd, n)) vmutils.ConfigureWithNewDataDisk(&role, "", destination, d, vmdisk.HostCachingTypeNone) case string: ui.Message(fmt.Sprintf("Configuring datadisk %d: existing blob (%s)...", n, d)) vmutils.ConfigureWithVhdDataDisk(&role, d, vmdisk.HostCachingTypeNone) default: err := fmt.Errorf("Datadisk %d is not a string nor a number", n) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } } state.Put("role", &role) return multistep.ActionContinue }
func (*StepValidate) Run(state multistep.StateBag) multistep.StepAction { client := state.Get(constants.RequestManager).(management.Client) ui := state.Get(constants.Ui).(packer.Ui) config := state.Get(constants.Config).(*Config) ui.Say("Validating Azure options...") role := vmutils.NewVMConfiguration(config.tmpVmName, config.InstanceSize) ui.Message("Checking Storage Account...") destinationVhd, err := validateStorageAccount(config, client) if err != nil { err = fmt.Errorf("Error checking storage account: %v", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } ui.Message(fmt.Sprintf("Destination VHD: %s", destinationVhd)) if err := func() error { if config.RemoteSourceImageLink != "" { ui.Message("Checking remote image source link...") response, err := http.DefaultClient.Head(config.RemoteSourceImageLink) if response != nil && response.Body != nil { defer response.Body.Close() } if err != nil { log.Printf("HTTP client returned error: %s", err) return fmt.Errorf("error checking remote image source link: %v", err) } if response.StatusCode != 200 { return fmt.Errorf("Unexpected status while retrieving remote image source at %s: %d %s", config.RemoteSourceImageLink, response.StatusCode, response.Status) } size := float64(response.ContentLength) / 1024 / 1024 / 1024 ui.Say(fmt.Sprintf("Remote image size: %.1f GiB", size)) vmutils.ConfigureDeploymentFromRemoteImage(&role, config.RemoteSourceImageLink, config.OSType, fmt.Sprintf("%s-OSDisk", config.tmpVmName), destinationVhd, "") } else { ui.Message("Checking image source...") imageList, err := osimage.NewClient(client).ListOSImages() if err != nil { log.Printf("OS image client returned error: %s", err) return err } if osImage, found := FindOSImage(imageList.OSImages, config.OSImageLabel, config.Location); found { vmutils.ConfigureDeploymentFromPlatformImage(&role, osImage.Name, destinationVhd, "") ui.Message(fmt.Sprintf("Image source is OS image %q", osImage.Name)) if osImage.OS != config.OSType { return fmt.Errorf("OS image type (%q) does not match config (%q)", osImage.OS, config.OSType) } } else { imageList, err := vmimage.NewClient(client).ListVirtualMachineImages() if err != nil { log.Printf("VM image client returned error: %s", err) return err } if vmImage, found := FindVmImage(imageList.VMImages, "", config.OSImageLabel, config.Location); found { vmutils.ConfigureDeploymentFromVMImage(&role, vmImage.Name, destinationVhd, true) ui.Message(fmt.Sprintf("Image source is VM image %q", vmImage.Name)) if vmImage.OSDiskConfiguration.OS != config.OSType { return fmt.Errorf("VM image type (%q) does not match config (%q)", vmImage.OSDiskConfiguration.OS, config.OSType) } } else { return fmt.Errorf("Can't find VM or OS image '%s' Located at '%s'", config.OSImageLabel, config.Location) } } } return nil }(); err != nil { err = fmt.Errorf("Error determining deployment source: %v", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } if config.OSType == constants.Target_Linux { certThumbprint := state.Get(constants.Thumbprint).(string) if len(certThumbprint) == 0 { err := fmt.Errorf("Certificate Thumbprint is empty") state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } vmutils.ConfigureForLinux(&role, config.tmpVmName, config.UserName, "", certThumbprint) vmutils.ConfigureWithPublicSSH(&role) } else if config.OSType == constants.Target_Windows { password := utils.RandomPassword() state.Put("password", password) vmutils.ConfigureForWindows(&role, config.tmpVmName, config.UserName, password, true, "") vmutils.ConfigureWithPublicRDP(&role) vmutils.ConfigureWithPublicPowerShell(&role) } if config.VNet != "" && config.Subnet != "" { ui.Message("Checking VNet...") if err := checkVirtualNetworkConfiguration(client, config.VNet, config.Subnet, config.Location); err != nil { state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } vmutils.ConfigureWithSubnet(&role, config.Subnet) } state.Put("role", &role) return multistep.ActionContinue }
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 }