func resourceArmVirtualMachineCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*ArmClient) vmClient := client.vmClient log.Printf("[INFO] preparing arguments for Azure ARM Virtual Machine creation.") name := d.Get("name").(string) location := d.Get("location").(string) resGroup := d.Get("resource_group_name").(string) tags := d.Get("tags").(map[string]interface{}) expandedTags := expandTags(tags) osDisk, err := expandAzureRmVirtualMachineOsDisk(d) if err != nil { return err } storageProfile := compute.StorageProfile{ OsDisk: osDisk, } if _, ok := d.GetOk("storage_image_reference"); ok { imageRef, err := expandAzureRmVirtualMachineImageReference(d) if err != nil { return err } storageProfile.ImageReference = imageRef } if _, ok := d.GetOk("storage_data_disk"); ok { dataDisks, err := expandAzureRmVirtualMachineDataDisk(d) if err != nil { return err } storageProfile.DataDisks = &dataDisks } networkProfile := expandAzureRmVirtualMachineNetworkProfile(d) vmSize := d.Get("vm_size").(string) properties := compute.VirtualMachineProperties{ NetworkProfile: &networkProfile, HardwareProfile: &compute.HardwareProfile{ VMSize: compute.VirtualMachineSizeTypes(vmSize), }, StorageProfile: &storageProfile, } osProfile, err := expandAzureRmVirtualMachineOsProfile(d) if err != nil { return err } properties.OsProfile = osProfile if v, ok := d.GetOk("availability_set_id"); ok { availabilitySet := v.(string) availSet := compute.SubResource{ ID: &availabilitySet, } properties.AvailabilitySet = &availSet } vm := compute.VirtualMachine{ Name: &name, Location: &location, Properties: &properties, Tags: expandedTags, } if _, ok := d.GetOk("plan"); ok { plan, err := expandAzureRmVirtualMachinePlan(d) if err != nil { return err } vm.Plan = plan } _, vmErr := vmClient.CreateOrUpdate(resGroup, name, vm, make(chan struct{})) if vmErr != nil { return vmErr } read, err := vmClient.Get(resGroup, name, "") if err != nil { return err } if read.ID == nil { return fmt.Errorf("Cannot read Virtual Machine %s (resource group %s) ID", name, resGroup) } d.SetId(*read.ID) return resourceArmVirtualMachineRead(d, meta) }
// createVirtualMachine creates a virtual machine and related resources. // // All resources created are tagged with the specified "vmTags", so if // this function fails then all resources can be deleted by tag. func createVirtualMachine( resourceGroup, location, vmName string, vmTags, envTags map[string]string, instanceSpec *instances.InstanceSpec, instanceConfig *instancecfg.InstanceConfig, distributionGroupFunc func() ([]instance.Id, error), instancesFunc func([]instance.Id) ([]instance.Instance, error), apiPort *int, internalNetworkSubnet *network.Subnet, nsgID, storageEndpoint, storageAccountName string, networkClient network.ManagementClient, vmClient compute.VirtualMachinesClient, availabilitySetClient compute.AvailabilitySetsClient, vmExtensionClient compute.VirtualMachineExtensionsClient, ) (compute.VirtualMachine, error) { storageProfile, err := newStorageProfile( vmName, instanceConfig.Series, instanceSpec, storageEndpoint, storageAccountName, ) if err != nil { return compute.VirtualMachine{}, errors.Annotate(err, "creating storage profile") } osProfile, seriesOS, err := newOSProfile(vmName, instanceConfig) if err != nil { return compute.VirtualMachine{}, errors.Annotate(err, "creating OS profile") } networkProfile, err := newNetworkProfile( networkClient, vmName, apiPort, internalNetworkSubnet, nsgID, resourceGroup, location, vmTags, ) if err != nil { return compute.VirtualMachine{}, errors.Annotate(err, "creating network profile") } availabilitySetId, err := createAvailabilitySet( availabilitySetClient, vmName, resourceGroup, location, vmTags, envTags, distributionGroupFunc, instancesFunc, ) if err != nil { return compute.VirtualMachine{}, errors.Annotate(err, "creating availability set") } vmArgs := compute.VirtualMachine{ Location: to.StringPtr(location), Tags: toTagsPtr(vmTags), Properties: &compute.VirtualMachineProperties{ HardwareProfile: &compute.HardwareProfile{ VMSize: compute.VirtualMachineSizeTypes( instanceSpec.InstanceType.Name, ), }, StorageProfile: storageProfile, OsProfile: osProfile, NetworkProfile: networkProfile, AvailabilitySet: &compute.SubResource{ ID: to.StringPtr(availabilitySetId), }, }, } vm, err := vmClient.CreateOrUpdate(resourceGroup, vmName, vmArgs) if err != nil { return compute.VirtualMachine{}, errors.Annotate(err, "creating virtual machine") } // On Windows and CentOS, we must add the CustomScript VM // extension to run the CustomData script. switch seriesOS { case os.Windows, os.CentOS: if err := createVMExtension( vmExtensionClient, seriesOS, resourceGroup, vmName, location, vmTags, ); err != nil { return compute.VirtualMachine{}, errors.Annotate( err, "creating virtual machine extension", ) } } return vm, nil }
func (a AzureClient) CreateVirtualMachine(resourceGroup, name, location, size, availabilitySetID, networkInterfaceID, username, sshPublicKey, imageName string, storageAccount *storage.AccountProperties) error { log.Info("Creating virtual machine.", logutil.Fields{ "name": name, "location": location, "size": size, "username": username, "osImage": imageName, }) img, err := parseImageName(imageName) if err != nil { return err } var ( osDiskBlobURL = osDiskStorageBlobURL(storageAccount, name) sshKeyPath = fmt.Sprintf("/home/%s/.ssh/authorized_keys", username) ) log.Debugf("OS disk blob will be placed at: %s", osDiskBlobURL) log.Debugf("SSH key will be placed at: %s", sshKeyPath) _, err = a.virtualMachinesClient().CreateOrUpdate(resourceGroup, name, compute.VirtualMachine{ Location: to.StringPtr(location), Properties: &compute.VirtualMachineProperties{ AvailabilitySet: &compute.SubResource{ ID: to.StringPtr(availabilitySetID), }, HardwareProfile: &compute.HardwareProfile{ VMSize: compute.VirtualMachineSizeTypes(size), }, NetworkProfile: &compute.NetworkProfile{ NetworkInterfaces: &[]compute.NetworkInterfaceReference{ { ID: to.StringPtr(networkInterfaceID), }, }, }, OsProfile: &compute.OSProfile{ ComputerName: to.StringPtr(name), AdminUsername: to.StringPtr(username), LinuxConfiguration: &compute.LinuxConfiguration{ DisablePasswordAuthentication: to.BoolPtr(true), SSH: &compute.SSHConfiguration{ PublicKeys: &[]compute.SSHPublicKey{ { Path: to.StringPtr(sshKeyPath), KeyData: to.StringPtr(sshPublicKey), }, }, }, }, }, StorageProfile: &compute.StorageProfile{ ImageReference: &compute.ImageReference{ Publisher: to.StringPtr(img.publisher), Offer: to.StringPtr(img.offer), Sku: to.StringPtr(img.sku), Version: to.StringPtr(img.version), }, OsDisk: &compute.OSDisk{ Name: to.StringPtr(fmt.Sprintf(fmtOSDiskResourceName, name)), Caching: compute.ReadWrite, CreateOption: compute.FromImage, Vhd: &compute.VirtualHardDisk{ URI: to.StringPtr(osDiskBlobURL), }, }, }, }, }, nil) return err }
func resourceArmVirtualMachineCreate(d *schema.ResourceData, meta interface{}) error { client := meta.(*ArmClient) vmClient := client.vmClient log.Printf("[INFO] preparing arguments for Azure ARM Virtual Machine creation.") name := d.Get("name").(string) location := d.Get("location").(string) resGroup := d.Get("resource_group_name").(string) tags := d.Get("tags").(map[string]interface{}) expandedTags := expandTags(tags) osDisk, err := expandAzureRmVirtualMachineOsDisk(d) if err != nil { return err } storageProfile := compute.StorageProfile{ OsDisk: osDisk, } if _, ok := d.GetOk("storage_image_reference"); ok { imageRef, err := expandAzureRmVirtualMachineImageReference(d) if err != nil { return err } storageProfile.ImageReference = imageRef } if _, ok := d.GetOk("storage_data_disk"); ok { dataDisks, err := expandAzureRmVirtualMachineDataDisk(d) if err != nil { return err } storageProfile.DataDisks = &dataDisks } networkProfile := expandAzureRmVirtualMachineNetworkProfile(d) vmSize := d.Get("vm_size").(string) properties := compute.VirtualMachineProperties{ NetworkProfile: &networkProfile, HardwareProfile: &compute.HardwareProfile{ VMSize: compute.VirtualMachineSizeTypes(vmSize), }, StorageProfile: &storageProfile, } osProfile, err := expandAzureRmVirtualMachineOsProfile(d) if err != nil { return err } properties.OsProfile = osProfile if v, ok := d.GetOk("availability_set_id"); ok { availabilitySet := v.(string) availSet := compute.SubResource{ ID: &availabilitySet, } properties.AvailabilitySet = &availSet } vm := compute.VirtualMachine{ Name: &name, Location: &location, Properties: &properties, Tags: expandedTags, } if _, ok := d.GetOk("plan"); ok { plan, err := expandAzureRmVirtualMachinePlan(d) if err != nil { return err } vm.Plan = plan } resp, vmErr := vmClient.CreateOrUpdate(resGroup, name, vm) if vmErr != nil { return vmErr } d.SetId(*resp.ID) log.Printf("[DEBUG] Waiting for Virtual Machine (%s) to become available", name) stateConf := &resource.StateChangeConf{ Pending: []string{"Creating", "Updating"}, Target: []string{"Succeeded"}, Refresh: virtualMachineStateRefreshFunc(client, resGroup, name), Timeout: 20 * time.Minute, MinTimeout: 10 * time.Second, } if _, err := stateConf.WaitForState(); err != nil { return fmt.Errorf("Error waiting for Virtual Machine (%s) to become available: %s", name, err) } return resourceArmVirtualMachineRead(d, meta) }
// createVirtualMachine creates a virtual machine and related resources. // // All resources created are tagged with the specified "vmTags", so if // this function fails then all resources can be deleted by tag. func (env *azureEnviron) createVirtualMachine( vmName string, vmTags, envTags map[string]string, instanceSpec *instances.InstanceSpec, instanceConfig *instancecfg.InstanceConfig, storageAccountType string, ) error { deploymentsClient := resources.DeploymentsClient{env.resources} var apiPort int if instanceConfig.Controller != nil { apiPortValue := instanceConfig.Controller.Config.APIPort() apiPort = apiPortValue } else { apiPorts := instanceConfig.APIInfo.Ports() if len(apiPorts) != 1 { return errors.Errorf("expected one API port, found %v", apiPorts) } apiPort = apiPorts[0] } resources := networkTemplateResources(env.location, envTags, apiPort) resources = append(resources, storageAccountTemplateResource( env.location, envTags, env.storageAccountName, storageAccountType, )) osProfile, seriesOS, err := newOSProfile( vmName, instanceConfig, env.provider.config.RandomWindowsAdminPassword, ) if err != nil { return errors.Annotate(err, "creating OS profile") } storageProfile, err := newStorageProfile(vmName, env.storageAccountName, instanceSpec) if err != nil { return errors.Annotate(err, "creating storage profile") } var vmDependsOn []string var availabilitySetSubResource *compute.SubResource availabilitySetName, err := availabilitySetName( vmName, vmTags, instanceConfig.Controller != nil, ) if err != nil { return errors.Annotate(err, "getting availability set name") } if availabilitySetName != "" { availabilitySetId := fmt.Sprintf( `[resourceId('Microsoft.Compute/availabilitySets','%s')]`, availabilitySetName, ) resources = append(resources, armtemplates.Resource{ APIVersion: compute.APIVersion, Type: "Microsoft.Compute/availabilitySets", Name: availabilitySetName, Location: env.location, Tags: envTags, }) availabilitySetSubResource = &compute.SubResource{ ID: to.StringPtr(availabilitySetId), } vmDependsOn = append(vmDependsOn, availabilitySetId) } publicIPAddressName := vmName + "-public-ip" publicIPAddressId := fmt.Sprintf(`[resourceId('Microsoft.Network/publicIPAddresses', '%s')]`, publicIPAddressName) resources = append(resources, armtemplates.Resource{ APIVersion: network.APIVersion, Type: "Microsoft.Network/publicIPAddresses", Name: publicIPAddressName, Location: env.location, Tags: vmTags, Properties: &network.PublicIPAddressPropertiesFormat{ PublicIPAllocationMethod: network.Dynamic, }, }) // Controller and non-controller machines are assigned to separate // subnets. This enables us to create controller-specific NSG rules // just by targeting the controller subnet. subnetName := internalSubnetName subnetPrefix := internalSubnetPrefix if instanceConfig.Controller != nil { subnetName = controllerSubnetName subnetPrefix = controllerSubnetPrefix } subnetId := fmt.Sprintf( `[concat(resourceId('Microsoft.Network/virtualNetworks', '%s'), '/subnets/%s')]`, internalNetworkName, subnetName, ) privateIP, err := machineSubnetIP(subnetPrefix, instanceConfig.MachineId) if err != nil { return errors.Annotatef(err, "computing private IP address") } nicName := vmName + "-primary" nicId := fmt.Sprintf(`[resourceId('Microsoft.Network/networkInterfaces', '%s')]`, nicName) ipConfigurations := []network.InterfaceIPConfiguration{{ Name: to.StringPtr("primary"), Properties: &network.InterfaceIPConfigurationPropertiesFormat{ Primary: to.BoolPtr(true), PrivateIPAddress: to.StringPtr(privateIP.String()), PrivateIPAllocationMethod: network.Static, Subnet: &network.Subnet{ID: to.StringPtr(subnetId)}, PublicIPAddress: &network.PublicIPAddress{ ID: to.StringPtr(publicIPAddressId), }, }, }} resources = append(resources, armtemplates.Resource{ APIVersion: network.APIVersion, Type: "Microsoft.Network/networkInterfaces", Name: nicName, Location: env.location, Tags: vmTags, Properties: &network.InterfacePropertiesFormat{ IPConfigurations: &ipConfigurations, }, DependsOn: []string{ publicIPAddressId, fmt.Sprintf( `[resourceId('Microsoft.Network/virtualNetworks', '%s')]`, internalNetworkName, ), }, }) nics := []compute.NetworkInterfaceReference{{ ID: to.StringPtr(nicId), Properties: &compute.NetworkInterfaceReferenceProperties{ Primary: to.BoolPtr(true), }, }} vmDependsOn = append(vmDependsOn, nicId) vmDependsOn = append(vmDependsOn, fmt.Sprintf( `[resourceId('Microsoft.Storage/storageAccounts', '%s')]`, env.storageAccountName, )) resources = append(resources, armtemplates.Resource{ APIVersion: compute.APIVersion, Type: "Microsoft.Compute/virtualMachines", Name: vmName, Location: env.location, Tags: vmTags, Properties: &compute.VirtualMachineProperties{ HardwareProfile: &compute.HardwareProfile{ VMSize: compute.VirtualMachineSizeTypes( instanceSpec.InstanceType.Name, ), }, StorageProfile: storageProfile, OsProfile: osProfile, NetworkProfile: &compute.NetworkProfile{ &nics, }, AvailabilitySet: availabilitySetSubResource, }, DependsOn: vmDependsOn, }) // On Windows and CentOS, we must add the CustomScript VM // extension to run the CustomData script. switch seriesOS { case os.Windows, os.CentOS: properties, err := vmExtensionProperties(seriesOS) if err != nil { return errors.Annotate( err, "creating virtual machine extension", ) } resources = append(resources, armtemplates.Resource{ APIVersion: compute.APIVersion, Type: "Microsoft.Compute/virtualMachines/extensions", Name: vmName + "/" + extensionName, Location: env.location, Tags: vmTags, Properties: properties, DependsOn: []string{"Microsoft.Compute/virtualMachines/" + vmName}, }) } logger.Debugf("- creating virtual machine deployment") template := armtemplates.Template{Resources: resources} // NOTE(axw) VMs take a long time to go to "Succeeded", so we do not // block waiting for them to be fully provisioned. This means we won't // return an error from StartInstance if the VM fails provisioning; // we will instead report the error via the instance's status. deploymentsClient.ResponseInspector = asyncCreationRespondDecorator( deploymentsClient.ResponseInspector, ) if err := createDeployment( env.callAPI, deploymentsClient, env.resourceGroup, vmName, // deployment name template, ); err != nil { return errors.Trace(err) } return nil }
func (clst *azureCluster) configureVirtualMachine(vmName string, osDiskName string, nicName string, cloudConfig string, vmSize string, location string, iface network.Interface) error { hardwareProfile := compute.HardwareProfile{ VMSize: compute.VirtualMachineSizeTypes(vmSize), } ifaceRef := compute.NetworkInterfaceReference{ ID: iface.ID, } networkProfile := compute.NetworkProfile{ NetworkInterfaces: &[]compute.NetworkInterfaceReference{ifaceRef}, } storageAccounts, err := clst.listStorageAccounts() if err != nil { return err } storageAccount, ok := storageAccounts[location] if !ok { return errors.New("a storage account is needed for location " + location) } vhdURI := fmt.Sprintf("http://%s.blob.core.windows.net/vhds/%s.vhd", *storageAccount.Name, osDiskName) vhd := compute.VirtualHardDisk{ URI: &vhdURI, } osDisk := compute.OSDisk{ Name: &osDiskName, Caching: compute.ReadWrite, CreateOption: compute.FromImage, Vhd: &vhd, } imageRef := compute.ImageReference{ Publisher: stringPtr(imagePublisher), Offer: stringPtr(imageOffer), Sku: stringPtr(imageSku), Version: stringPtr(imageVersion), } storageProfile := compute.StorageProfile{ ImageReference: &imageRef, OsDisk: &osDisk, } // We have to set username and password even though we do not need it. adminUsername := uuid.NewV4().String() adminPassword := uuid.NewV4().String() customData := base64.StdEncoding.EncodeToString([]byte(cloudConfig)) osProfile := compute.OSProfile{ ComputerName: &vmName, AdminUsername: &adminUsername, AdminPassword: &adminPassword, CustomData: &customData, } properties := compute.VirtualMachineProperties{ HardwareProfile: &hardwareProfile, NetworkProfile: &networkProfile, StorageProfile: &storageProfile, OsProfile: &osProfile, } virtualMachine := compute.VirtualMachine{ Name: &vmName, Location: &location, Properties: &properties, Tags: &map[string]*string{nsTag: &clst.namespace}, } cancel := make(chan struct{}) _, err = clst.azureClient.vmCreate(resourceGroupName, vmName, virtualMachine, cancel) return err }