示例#1
0
//
// configureForLinux sets up the VM role for Linux specific configuration
//
// Paramters:
//   role: role that needs to be updated with Linux configuration
//   dnsName: name of the machine that we are trying to create
//
// Returns:
//   error: errors from reading certs, getting thumbprint and adding
//   certificate to hostedservice
//
func (d *Driver) configureForLinux(role *virtualmachine.Role, dnsName string) error {

	// Get the Azure client
	client, err := d.getClient()
	if err != nil {
		return err
	}

	mediaLink := fmt.Sprintf("http://%s.blob.core.windows.net/vhds/%s.vhd",
		d.StorageAccount, dnsName)

	// Setup the image configuration
	vmutils.ConfigureDeploymentFromPlatformImage(
		role,
		d.Image,
		mediaLink,
		"")

	// Read the certificate
	data, err := ioutil.ReadFile(d.azureCertPath())
	if err != nil {
		return err
	}

	// Add the certificate to the hostedservice
	if _, err := hostedservice.NewClient(client).AddCertificate(dnsName, data, "pfx", ""); err != nil {
		return err
	}

	thumbPrint, err := getServiceCertFingerprint(d.azureCertPath())
	if err != nil {
		return err
	}

	vmutils.ConfigureForLinux(role, dnsName, d.SSHUser, d.UserPassword, thumbPrint)
	vmutils.ConfigureWithPublicSSH(role)

	role.UseCertAuth = true
	role.CertPath = d.azureCertPath()

	// Attach VM to a specific subnet
	if d.Subnet != "" {
		err = vmutils.ConfigureWithSubnet(role, d.Subnet)
		if err != nil {
			log.Error("failed to configure subnet:", d.Subnet, ", err:", err)
			return err
		}
		log.Debug("subnet is:", d.Subnet)
	}

	return nil
}
func resourceAzureInstanceCreate(d *schema.ResourceData, meta interface{}) (err error) {
	azureClient := meta.(*Client)
	mc := azureClient.mgmtClient
	hostedServiceClient := azureClient.hostedServiceClient
	vmClient := azureClient.vmClient

	name := d.Get("name").(string)

	// Compute/set the description
	description := d.Get("description").(string)
	if description == "" {
		description = name
	}

	// Retrieve the needed details of the image
	configureForImage, osType, err := retrieveImageDetails(
		meta,
		d.Get("image").(string),
		name,
		d.Get("storage_service_name").(string),
	)
	if err != nil {
		return err
	}

	// Verify if we have all required parameters
	if err := verifyInstanceParameters(d, osType); err != nil {
		return err
	}

	var hostedServiceName string
	// check if hosted service name parameter was given:
	if serviceName, ok := d.GetOk("hosted_service_name"); !ok {
		// if not provided; just use the name of the instance to create a new one:
		hostedServiceName = name
		d.Set("hosted_service_name", hostedServiceName)

		p := hostedservice.CreateHostedServiceParameters{
			ServiceName:    hostedServiceName,
			Label:          base64.StdEncoding.EncodeToString([]byte(name)),
			Description:    fmt.Sprintf("Cloud Service created automatically for instance %s", name),
			Location:       d.Get("location").(string),
			ReverseDNSFqdn: d.Get("reverse_dns").(string),
		}

		log.Printf("[DEBUG] Creating Cloud Service for instance: %s", name)
		err = hostedServiceClient.CreateHostedService(p)
		if err != nil {
			return fmt.Errorf("Error creating Cloud Service for instance %s: %s", name, err)
		}
	} else {
		// else; use the provided hosted service name:
		hostedServiceName = serviceName.(string)
	}

	// Create a new role for the instance
	role := vmutils.NewVMConfiguration(name, d.Get("size").(string))

	log.Printf("[DEBUG] Configuring deployment from image...")
	err = configureForImage(&role)
	if err != nil {
		return fmt.Errorf("Error configuring the deployment for %s: %s", name, err)
	}

	if osType == linux {
		// This is pretty ugly, but the Azure SDK leaves me no other choice...
		if tp, ok := d.GetOk("ssh_key_thumbprint"); ok {
			err = vmutils.ConfigureForLinux(
				&role,
				name,
				d.Get("username").(string),
				d.Get("password").(string),
				tp.(string),
			)
		} else {
			err = vmutils.ConfigureForLinux(
				&role,
				name,
				d.Get("username").(string),
				d.Get("password").(string),
			)
		}
		if err != nil {
			return fmt.Errorf("Error configuring %s for Linux: %s", name, err)
		}
	}

	if osType == windows {
		err = vmutils.ConfigureForWindows(
			&role,
			name,
			d.Get("username").(string),
			d.Get("password").(string),
			d.Get("automatic_updates").(bool),
			d.Get("time_zone").(string),
		)
		if err != nil {
			return fmt.Errorf("Error configuring %s for Windows: %s", name, err)
		}

		if domain_name, ok := d.GetOk("domain_name"); ok {
			err = vmutils.ConfigureWindowsToJoinDomain(
				&role,
				d.Get("domain_username").(string),
				d.Get("domain_password").(string),
				domain_name.(string),
				d.Get("domain_ou").(string),
			)
			if err != nil {
				return fmt.Errorf("Error configuring %s for WindowsToJoinDomain: %s", name, err)
			}
		}
	}

	if s := d.Get("endpoint").(*schema.Set); s.Len() > 0 {
		for _, v := range s.List() {
			m := v.(map[string]interface{})
			err := vmutils.ConfigureWithExternalPort(
				&role,
				m["name"].(string),
				m["private_port"].(int),
				m["public_port"].(int),
				endpointProtocol(m["protocol"].(string)),
			)
			if err != nil {
				return fmt.Errorf(
					"Error adding endpoint %s for instance %s: %s", m["name"].(string), name, err)
			}
		}
	}

	if subnet, ok := d.GetOk("subnet"); ok {
		err = vmutils.ConfigureWithSubnet(&role, subnet.(string))
		if err != nil {
			return fmt.Errorf(
				"Error associating subnet %s with instance %s: %s", d.Get("subnet").(string), name, err)
		}
	}

	if sg, ok := d.GetOk("security_group"); ok {
		err = vmutils.ConfigureWithSecurityGroup(&role, sg.(string))
		if err != nil {
			return fmt.Errorf(
				"Error associating security group %s with instance %s: %s", sg.(string), name, err)
		}
	}

	options := virtualmachine.CreateDeploymentOptions{
		VirtualNetworkName: d.Get("virtual_network").(string),
	}

	log.Printf("[DEBUG] Creating the new instance...")
	req, err := vmClient.CreateDeployment(role, hostedServiceName, options)
	if err != nil {
		return fmt.Errorf("Error creating instance %s: %s", name, err)
	}

	log.Printf("[DEBUG] Waiting for the new instance to be created...")
	if err := mc.WaitForOperation(req, nil); err != nil {
		return fmt.Errorf(
			"Error waiting for instance %s to be created: %s", name, err)
	}

	d.SetId(name)

	return resourceAzureInstanceRead(d, meta)
}
示例#3
0
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
}
示例#4
0
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
}
示例#5
0
//
// configureForWindows sets up the VM role for Windows specific configuration
//
// Paramters:
//   role: role that needs to be updated with Windows configuration
//   dnsName: name of the machine that we are trying to create
//
// Returns:
//   None
//
func (d *Driver) configureForWindows(role *virtualmachine.Role, dnsName string) error {

	// Get the Azure client
	client, err := d.getClient()
	if err != nil {
		return err
	}

	mediaLocation := fmt.Sprintf("http://%s.blob.core.windows.net/vhds/%s.vhd",
		d.StorageAccount, dnsName)

	// Setup the image configuration
	vmutils.ConfigureDeploymentFromPlatformImage(
		role,
		d.Image,
		mediaLocation,
		"")
	log.Debug("Configured deployment from platform image")

	vmutils.ConfigureForWindows(role, dnsName, d.SSHUser, d.UserPassword, true, "")
	log.Debug("Configured for windows")

	vmutils.ConfigureWithPublicSSH(role)
	log.Debug("Configured for SSH")

	vmutils.ConfigureWithPublicRDP(role)
	log.Debug("Configured for RDP")

	vmutils.ConfigureWithPublicPowerShell(role)
	log.Debug("Configured with Powershell")

	vmutils.ConfigureWithExternalPort(role, "WinRMu", 5985, 5985,
		virtualmachine.InputEndpointProtocolTCP)
	log.Debug("Configured WinRM port 5985")

	// Read the certificate
	data, err := ioutil.ReadFile(d.azureCertPath())
	if err != nil {
		return err
	}
	log.Debug("Read certificate from Azure cert path: ", d.azureCertPath())

	// Add the certificate to the hostedservice
	if _, err := hostedservice.NewClient(client).AddCertificate(dnsName, data, "pfx", ""); err != nil {
		log.Error("failed to add certificate:", err)
		return err
	}
	log.Debug("Added certificate to hostedservice")

	vmutils.ConfigureWinRMOverHTTP(role)
	log.Debug("Configured WinRM over HTTP")

	vmutils.ConfigureWinRMOverHTTPS(role, "")
	log.Debug("Configured WinRM over HTTPS without using a thumbprint")

	// Attach VM to a specific subnet
	if d.Subnet != "" {
		err = vmutils.ConfigureWithSubnet(role, d.Subnet)
		if err != nil {
			log.Error("failed to configure subnet:", d.Subnet, ", err:", err)
			return err
		}
		log.Debug("subnet is:", d.Subnet)
	}

	return nil
}