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)
}
func resourceAzureInstanceUpdate(d *schema.ResourceData, meta interface{}) error {
	azureClient := meta.(*Client)
	mc := azureClient.mgmtClient
	vmClient := azureClient.vmClient

	// First check if anything we can update changed, and if not just return
	if !d.HasChange("size") && !d.HasChange("endpoint") && !d.HasChange("security_group") {
		return nil
	}

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

	// Get the current role
	role, err := vmClient.GetRole(hostedServiceName, name, name)
	if err != nil {
		return fmt.Errorf("Error retrieving role of instance %s: %s", name, err)
	}

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

	if d.HasChange("size") {
		role.RoleSize = d.Get("size").(string)
	}

	if d.HasChange("endpoint") {
		_, n := d.GetChange("endpoint")

		// Delete the existing endpoints
		for i, c := range role.ConfigurationSets {
			if c.ConfigurationSetType == virtualmachine.ConfigurationSetTypeNetwork {
				c.InputEndpoints = nil
				role.ConfigurationSets[i] = c
			}
		}

		// And add the ones we still want
		if s := n.(*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 d.HasChange("security_group") {
		sg := d.Get("security_group").(string)
		err := vmutils.ConfigureWithSecurityGroup(role, sg)
		if err != nil {
			return fmt.Errorf(
				"Error associating security group %s with instance %s: %s", sg, name, err)
		}
	}

	// Update the adjusted role
	req, err := vmClient.UpdateRole(hostedServiceName, name, name, *role)
	if err != nil {
		return fmt.Errorf("Error updating role of instance %s: %s", name, err)
	}

	if err := mc.WaitForOperation(req, nil); err != nil {
		return fmt.Errorf(
			"Error waiting for role of instance %s to be updated: %s", name, err)
	}

	return resourceAzureInstanceRead(d, meta)
}
Example #3
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
}