Example #1
0
File: instance.go Project: bac/juju
// interfacePublicIPAddresses lists all public IP addresses in the resource
// group, and returns a mapping from instance ID to the public IP addresses
// associated with that instance.
func instancePublicIPAddresses(
	callAPI callAPIFunc,
	resourceGroup string,
	pipClient network.PublicIPAddressesClient,
) (map[instance.Id][]network.PublicIPAddress, error) {
	var pipsResult network.PublicIPAddressListResult
	if err := callAPI(func() (autorest.Response, error) {
		var err error
		pipsResult, err = pipClient.List(resourceGroup)
		return pipsResult.Response, err
	}); err != nil {
		return nil, errors.Annotate(err, "listing public IP addresses")
	}
	if pipsResult.Value == nil || len(*pipsResult.Value) == 0 {
		return nil, nil
	}
	instancePips := make(map[instance.Id][]network.PublicIPAddress)
	for _, pip := range *pipsResult.Value {
		instanceId := instance.Id(toTags(pip.Tags)[jujuMachineNameTag])
		instancePips[instanceId] = append(instancePips[instanceId], pip)
	}
	return instancePips, nil
}
Example #2
0
// setInstanceAddresses queries Azure for the NICs and public IPs associated
// with the given set of instances. This assumes that the instances'
// VirtualMachines are up-to-date, and that there are no concurrent accesses
// to the instances.
func setInstanceAddresses(
	pipClient network.PublicIPAddressesClient,
	resourceGroup string,
	instances []*azureInstance,
	nicsResult network.InterfaceListResult,
) (err error) {

	instanceNics := make(map[instance.Id][]network.Interface)
	instancePips := make(map[instance.Id][]network.PublicIPAddress)
	for _, inst := range instances {
		instanceNics[inst.Id()] = nil
		instancePips[inst.Id()] = nil
	}

	// When setAddresses returns without error, update each
	// instance's network interfaces and public IP addresses.
	setInstanceFields := func(inst *azureInstance) {
		inst.networkInterfaces = instanceNics[inst.Id()]
		inst.publicIPAddresses = instancePips[inst.Id()]
	}
	defer func() {
		if err != nil {
			return
		}
		for _, inst := range instances {
			setInstanceFields(inst)
		}
	}()

	// We do not rely on references because of how StopInstances works.
	// In order to not leak resources we must not delete the virtual
	// machine until after all of its dependencies are deleted.
	//
	// NICs and PIPs cannot be deleted until they have no references.
	// Thus, we cannot delete a PIP until there is no reference to it
	// in any NICs, and likewise we cannot delete a NIC until there
	// is no reference to it in any virtual machine.

	if nicsResult.Value != nil {
		for _, nic := range *nicsResult.Value {
			instanceId := instance.Id(toTags(nic.Tags)[jujuMachineNameTag])
			if _, ok := instanceNics[instanceId]; !ok {
				continue
			}
			instanceNics[instanceId] = append(instanceNics[instanceId], nic)
		}
	}

	pipsResult, err := pipClient.List(resourceGroup)
	if err != nil {
		return errors.Annotate(err, "listing public IP addresses")
	}
	if pipsResult.Value != nil {
		for _, pip := range *pipsResult.Value {
			instanceId := instance.Id(toTags(pip.Tags)[jujuMachineNameTag])
			if _, ok := instanceNics[instanceId]; !ok {
				continue
			}
			instancePips[instanceId] = append(instancePips[instanceId], pip)
		}
	}

	// Fields will be assigned to instances by the deferred call.
	return nil
}