Beispiel #1
0
// virtualMachines returns a mapping of instance IDs to VirtualMachines and
// errors, for each of the specified instance IDs.
func (v *azureVolumeSource) virtualMachines(instanceIds []instance.Id) (map[instance.Id]*maybeVirtualMachine, error) {
	vmsClient := compute.VirtualMachinesClient{v.env.compute}
	var result compute.VirtualMachineListResult
	if err := v.env.callAPI(func() (autorest.Response, error) {
		var err error
		result, err = vmsClient.List(v.env.resourceGroup)
		return result.Response, err
	}); err != nil {
		return nil, errors.Annotate(err, "listing virtual machines")
	}

	all := make(map[instance.Id]*compute.VirtualMachine)
	if result.Value != nil {
		for _, vm := range *result.Value {
			vmCopy := vm
			all[instance.Id(to.String(vm.Name))] = &vmCopy
		}
	}
	results := make(map[instance.Id]*maybeVirtualMachine)
	for _, id := range instanceIds {
		result := &maybeVirtualMachine{vm: all[id]}
		if result.vm == nil {
			result.err = errors.NotFoundf("instance %v", id)
		}
		results[id] = result
	}
	return results, nil
}
Beispiel #2
0
// allInstances returns all of the instances in the given resource group,
// and optionally ensures that each instance's addresses are up-to-date.
func (env *azureEnviron) allInstances(
	resourceGroup string,
	refreshAddresses bool,
) ([]instance.Instance, error) {
	env.mu.Lock()
	vmClient := compute.VirtualMachinesClient{env.compute}
	nicClient := network.InterfacesClient{env.network}
	pipClient := network.PublicIPAddressesClient{env.network}
	env.mu.Unlock()

	// Due to how deleting instances works, we have to get creative about
	// listing instances. We list NICs and return an instance for each
	// unique value of the jujuMachineNameTag tag.
	//
	// The machine provisioner will call AllInstances so it can delete
	// unknown instances. StopInstances must delete VMs before NICs and
	// public IPs, because a VM cannot have less than 1 NIC. Thus, we can
	// potentially delete a VM but then fail to delete its NIC.
	nicsResult, err := nicClient.List(resourceGroup)
	if err != nil {
		if nicsResult.Response.Response != nil && nicsResult.StatusCode == http.StatusNotFound {
			// This will occur if the resource group does not
			// exist, e.g. in a fresh hosted environment.
			return nil, nil
		}
		return nil, errors.Trace(err)
	}
	if nicsResult.Value == nil || len(*nicsResult.Value) == 0 {
		return nil, nil
	}

	// Create an azureInstance for each VM.
	result, err := vmClient.List(resourceGroup)
	if err != nil {
		return nil, errors.Annotate(err, "listing virtual machines")
	}
	vmNames := make(set.Strings)
	var azureInstances []*azureInstance
	if result.Value != nil {
		azureInstances = make([]*azureInstance, len(*result.Value))
		for i, vm := range *result.Value {
			inst := &azureInstance{vm, env, nil, nil}
			azureInstances[i] = inst
			vmNames.Add(to.String(vm.Name))
		}
	}

	// Create additional azureInstances for NICs without machines. See
	// comments above for rationale. This needs to happen before calling
	// setInstanceAddresses, so we still associate the NICs/PIPs.
	for _, nic := range *nicsResult.Value {
		vmName, ok := toTags(nic.Tags)[jujuMachineNameTag]
		if !ok || vmNames.Contains(vmName) {
			continue
		}
		vm := compute.VirtualMachine{
			Name: to.StringPtr(vmName),
			Properties: &compute.VirtualMachineProperties{
				ProvisioningState: to.StringPtr("Partially Deleted"),
			},
		}
		inst := &azureInstance{vm, env, nil, nil}
		azureInstances = append(azureInstances, inst)
		vmNames.Add(to.String(vm.Name))
	}

	if len(azureInstances) > 0 && refreshAddresses {
		if err := setInstanceAddresses(
			pipClient, resourceGroup, azureInstances, nicsResult,
		); err != nil {
			return nil, errors.Trace(err)
		}
	}
	instances := make([]instance.Instance, len(azureInstances))
	for i, inst := range azureInstances {
		instances[i] = inst
	}
	return instances, nil
}