github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/state/machine_linklayerdevices.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package state
     5  
     6  import (
     7  	"fmt"
     8  	"math/rand"
     9  	"net"
    10  
    11  	"github.com/juju/errors"
    12  	"github.com/juju/utils/set"
    13  	"gopkg.in/mgo.v2"
    14  	"gopkg.in/mgo.v2/bson"
    15  	"gopkg.in/mgo.v2/txn"
    16  
    17  	"github.com/juju/juju/container"
    18  	"github.com/juju/juju/network"
    19  )
    20  
    21  // LinkLayerDevice returns the link-layer device matching the given name. An
    22  // error satisfying errors.IsNotFound() is returned when no such device exists
    23  // on the machine.
    24  func (m *Machine) LinkLayerDevice(name string) (*LinkLayerDevice, error) {
    25  	linkLayerDevices, closer := m.st.getCollection(linkLayerDevicesC)
    26  	defer closer()
    27  
    28  	linkLayerDeviceDocID := m.linkLayerDeviceDocIDFromName(name)
    29  	deviceAsString := m.deviceAsStringFromName(name)
    30  
    31  	var doc linkLayerDeviceDoc
    32  	err := linkLayerDevices.FindId(linkLayerDeviceDocID).One(&doc)
    33  	if err == mgo.ErrNotFound {
    34  		return nil, errors.NotFoundf("%s", deviceAsString)
    35  	} else if err != nil {
    36  		return nil, errors.Annotatef(err, "cannot get %s", deviceAsString)
    37  	}
    38  	return newLinkLayerDevice(m.st, doc), nil
    39  }
    40  
    41  func (m *Machine) linkLayerDeviceDocIDFromName(deviceName string) string {
    42  	return m.st.docID(m.linkLayerDeviceGlobalKeyFromName(deviceName))
    43  }
    44  
    45  func (m *Machine) linkLayerDeviceGlobalKeyFromName(deviceName string) string {
    46  	return linkLayerDeviceGlobalKey(m.doc.Id, deviceName)
    47  }
    48  
    49  func (m *Machine) deviceAsStringFromName(deviceName string) string {
    50  	return fmt.Sprintf("device %q on machine %q", deviceName, m.doc.Id)
    51  }
    52  
    53  // AllLinkLayerDevices returns all exiting link-layer devices of the machine.
    54  func (m *Machine) AllLinkLayerDevices() ([]*LinkLayerDevice, error) {
    55  	var allDevices []*LinkLayerDevice
    56  	callbackFunc := func(resultDoc *linkLayerDeviceDoc) {
    57  		allDevices = append(allDevices, newLinkLayerDevice(m.st, *resultDoc))
    58  	}
    59  
    60  	if err := m.forEachLinkLayerDeviceDoc(nil, callbackFunc); err != nil {
    61  		return nil, errors.Trace(err)
    62  	}
    63  	return allDevices, nil
    64  }
    65  
    66  func (m *Machine) forEachLinkLayerDeviceDoc(docFieldsToSelect bson.D, callbackFunc func(resultDoc *linkLayerDeviceDoc)) error {
    67  	linkLayerDevices, closer := m.st.getCollection(linkLayerDevicesC)
    68  	defer closer()
    69  
    70  	query := linkLayerDevices.Find(bson.D{{"machine-id", m.doc.Id}})
    71  	if docFieldsToSelect != nil {
    72  		query = query.Select(docFieldsToSelect)
    73  	}
    74  	iter := query.Iter()
    75  
    76  	var resultDoc linkLayerDeviceDoc
    77  	for iter.Next(&resultDoc) {
    78  		callbackFunc(&resultDoc)
    79  	}
    80  
    81  	return errors.Trace(iter.Close())
    82  }
    83  
    84  // AllProviderInterfaceInfos returns the provider details for all of
    85  // the link layer devices belonging to this machine. These can be used
    86  // to identify the devices when interacting with the provider
    87  // directly (for example, releasing container addresses).
    88  func (m *Machine) AllProviderInterfaceInfos() ([]network.ProviderInterfaceInfo, error) {
    89  	devices, err := m.AllLinkLayerDevices()
    90  	if err != nil {
    91  		return nil, errors.Trace(err)
    92  	}
    93  	result := make([]network.ProviderInterfaceInfo, len(devices))
    94  	for i, device := range devices {
    95  		result[i].InterfaceName = device.Name()
    96  		result[i].MACAddress = device.MACAddress()
    97  		result[i].ProviderId = device.ProviderID()
    98  	}
    99  	return result, nil
   100  }
   101  
   102  // RemoveAllLinkLayerDevices removes all existing link-layer devices of the
   103  // machine in a single transaction. No error is returned when some or all of the
   104  // devices were already removed.
   105  func (m *Machine) RemoveAllLinkLayerDevices() error {
   106  	ops, err := m.removeAllLinkLayerDevicesOps()
   107  	if err != nil {
   108  		return errors.Trace(err)
   109  	}
   110  
   111  	return m.st.runTransaction(ops)
   112  }
   113  
   114  func (m *Machine) removeAllLinkLayerDevicesOps() ([]txn.Op, error) {
   115  	var ops []txn.Op
   116  	callbackFunc := func(resultDoc *linkLayerDeviceDoc) {
   117  		removeOps := removeLinkLayerDeviceUnconditionallyOps(resultDoc.DocID)
   118  		ops = append(ops, removeOps...)
   119  		if resultDoc.ProviderID != "" {
   120  			providerId := network.Id(resultDoc.ProviderID)
   121  			op := m.st.networkEntityGlobalKeyRemoveOp("linklayerdevice", providerId)
   122  			ops = append(ops, op)
   123  		}
   124  	}
   125  
   126  	selectDocIDOnly := bson.D{{"_id", 1}}
   127  	if err := m.forEachLinkLayerDeviceDoc(selectDocIDOnly, callbackFunc); err != nil {
   128  		return nil, errors.Trace(err)
   129  	}
   130  
   131  	return ops, nil
   132  }
   133  
   134  // LinkLayerDeviceArgs contains the arguments accepted by Machine.SetLinkLayerDevices().
   135  type LinkLayerDeviceArgs struct {
   136  	// Name is the name of the device as it appears on the machine.
   137  	Name string
   138  
   139  	// MTU is the maximum transmission unit the device can handle.
   140  	MTU uint
   141  
   142  	// ProviderID is a provider-specific ID of the device. Empty when not
   143  	// supported by the provider. Cannot be cleared once set.
   144  	ProviderID network.Id
   145  
   146  	// Type is the type of the underlying link-layer device.
   147  	Type LinkLayerDeviceType
   148  
   149  	// MACAddress is the media access control address for the device.
   150  	MACAddress string
   151  
   152  	// IsAutoStart is true if the device should be activated on boot.
   153  	IsAutoStart bool
   154  
   155  	// IsUp is true when the device is up (enabled).
   156  	IsUp bool
   157  
   158  	// ParentName is the name of the parent device, which may be empty. If set,
   159  	// it needs to be an existing device on the same machine, unless the current
   160  	// device is inside a container, in which case ParentName can be a global
   161  	// key of a BridgeDevice on the host machine of the container. Traffic
   162  	// originating from a device egresses from its parent device.
   163  	ParentName string
   164  }
   165  
   166  // SetLinkLayerDevices sets link-layer devices on the machine, adding or
   167  // updating existing devices as needed, in a single transaction. ProviderID
   168  // field can be empty if not supported by the provider, but when set must be
   169  // unique within the model, and cannot be unset once set. Errors are returned in
   170  // the following cases:
   171  // - Machine is no longer alive or is missing;
   172  // - Model no longer alive;
   173  // - errors.NotValidError, when any of the fields in args contain invalid values;
   174  // - ErrProviderIDNotUnique, when one or more specified ProviderIDs are not unique;
   175  // Setting new parent devices must be done in a separate call than setting their
   176  // children on the same machine.
   177  func (m *Machine) SetLinkLayerDevices(devicesArgs ...LinkLayerDeviceArgs) (err error) {
   178  	defer errors.DeferredAnnotatef(&err, "cannot set link-layer devices to machine %q", m.doc.Id)
   179  
   180  	if len(devicesArgs) == 0 {
   181  		logger.Warningf("no device addresses to set")
   182  		return nil
   183  	}
   184  
   185  	buildTxn := func(attempt int) ([]txn.Op, error) {
   186  		newDocs, err := m.prepareToSetLinkLayerDevices(devicesArgs)
   187  		if err != nil {
   188  			return nil, errors.Trace(err)
   189  		}
   190  
   191  		if attempt > 0 {
   192  			if err := checkModelActive(m.st); err != nil {
   193  				return nil, errors.Trace(err)
   194  			}
   195  			if err := m.isStillAlive(); err != nil {
   196  				return nil, errors.Trace(err)
   197  			}
   198  			allIds, err := m.st.allProviderIDsForLinkLayerDevices()
   199  			if err != nil {
   200  				return nil, errors.Trace(err)
   201  			}
   202  			for _, args := range devicesArgs {
   203  				if allIds.Contains(string(args.ProviderID)) {
   204  					err := NewProviderIDNotUniqueError(args.ProviderID)
   205  					return nil, errors.Annotatef(err, "invalid device %q", args.Name)
   206  				}
   207  			}
   208  		}
   209  
   210  		ops := []txn.Op{
   211  			assertModelActiveOp(m.st.ModelUUID()),
   212  			m.assertAliveOp(),
   213  		}
   214  
   215  		setDevicesOps, err := m.setDevicesFromDocsOps(newDocs)
   216  		if err != nil {
   217  			return nil, errors.Trace(err)
   218  		}
   219  		return append(ops, setDevicesOps...), nil
   220  	}
   221  	if err := m.st.run(buildTxn); err != nil {
   222  		return errors.Trace(err)
   223  	}
   224  	return nil
   225  }
   226  
   227  func (st *State) allProviderIDsForLinkLayerDevices() (set.Strings, error) {
   228  	return st.allProviderIDsForEntity("linklayerdevice")
   229  }
   230  
   231  func (st *State) allProviderIDsForAddresses() (set.Strings, error) {
   232  	return st.allProviderIDsForEntity("address")
   233  }
   234  
   235  func (st *State) allProviderIDsForEntity(entityName string) (set.Strings, error) {
   236  	idCollection, closer := st.getCollection(providerIDsC)
   237  	defer closer()
   238  
   239  	allProviderIDs := set.NewStrings()
   240  	var doc struct {
   241  		ID string `bson:"_id"`
   242  	}
   243  
   244  	pattern := fmt.Sprintf("^%s:%s:.+$", st.ModelUUID(), entityName)
   245  	modelProviderIDs := bson.D{{"_id", bson.D{{"$regex", pattern}}}}
   246  	iter := idCollection.Find(modelProviderIDs).Iter()
   247  	for iter.Next(&doc) {
   248  		localProviderID := st.localID(doc.ID)[len(entityName)+1:]
   249  		allProviderIDs.Add(localProviderID)
   250  	}
   251  	if err := iter.Close(); err != nil {
   252  		return nil, errors.Trace(err)
   253  	}
   254  	return allProviderIDs, nil
   255  }
   256  
   257  func (m *Machine) prepareToSetLinkLayerDevices(devicesArgs []LinkLayerDeviceArgs) ([]linkLayerDeviceDoc, error) {
   258  	var pendingDocs []linkLayerDeviceDoc
   259  	pendingNames := set.NewStrings()
   260  
   261  	for _, args := range devicesArgs {
   262  		newDoc, err := m.prepareOneSetLinkLayerDeviceArgs(&args, pendingNames)
   263  		if err != nil {
   264  			return nil, errors.Trace(err)
   265  		}
   266  		pendingNames.Add(args.Name)
   267  		pendingDocs = append(pendingDocs, *newDoc)
   268  	}
   269  	return pendingDocs, nil
   270  }
   271  
   272  func (m *Machine) prepareOneSetLinkLayerDeviceArgs(args *LinkLayerDeviceArgs, pendingNames set.Strings) (_ *linkLayerDeviceDoc, err error) {
   273  	defer errors.DeferredAnnotatef(&err, "invalid device %q", args.Name)
   274  
   275  	if err := m.validateSetLinkLayerDeviceArgs(args); err != nil {
   276  		return nil, errors.Trace(err)
   277  	}
   278  
   279  	if pendingNames.Contains(args.Name) {
   280  		return nil, errors.NewNotValid(nil, "Name specified more than once")
   281  	}
   282  
   283  	return m.newLinkLayerDeviceDocFromArgs(args), nil
   284  }
   285  
   286  func (m *Machine) validateSetLinkLayerDeviceArgs(args *LinkLayerDeviceArgs) error {
   287  	if args.Name == "" {
   288  		return errors.NotValidf("empty Name")
   289  	}
   290  	if !IsValidLinkLayerDeviceName(args.Name) {
   291  		logger.Warningf(
   292  			"link-layer device %q on machine %q has invalid name (using anyway)",
   293  			args.Name, m.Id(),
   294  		)
   295  	}
   296  
   297  	if args.ParentName != "" {
   298  		if err := m.validateLinkLayerDeviceParent(args); err != nil {
   299  			return errors.Trace(err)
   300  		}
   301  	}
   302  
   303  	if !IsValidLinkLayerDeviceType(string(args.Type)) {
   304  		return errors.NotValidf("Type %q", args.Type)
   305  	}
   306  
   307  	if args.MACAddress != "" {
   308  		if _, err := net.ParseMAC(args.MACAddress); err != nil {
   309  			return errors.NotValidf("MACAddress %q", args.MACAddress)
   310  		}
   311  	}
   312  	return nil
   313  }
   314  
   315  func (m *Machine) validateLinkLayerDeviceParent(args *LinkLayerDeviceArgs) error {
   316  	hostMachineID, parentDeviceName, err := parseLinkLayerDeviceParentNameAsGlobalKey(args.ParentName)
   317  	if err != nil {
   318  		return errors.Trace(err)
   319  	} else if hostMachineID == "" {
   320  		// Not a global key, so validate as usual.
   321  		if err := m.validateParentDeviceNameWhenNotAGlobalKey(args); errors.IsNotFound(err) {
   322  			return errors.NewNotValid(err, "ParentName not valid")
   323  		} else if err != nil {
   324  			return errors.Trace(err)
   325  		}
   326  		return nil
   327  	}
   328  	ourParentMachineID, hasParent := m.ParentId()
   329  	if !hasParent {
   330  		// Using global key for ParentName not allowed for non-container machine
   331  		// devices.
   332  		return errors.NotValidf("ParentName %q for non-container machine %q", args.ParentName, m.Id())
   333  	}
   334  	if hostMachineID != ourParentMachineID {
   335  		// ParentName as global key only allowed when the key's machine ID is
   336  		// the container's host machine.
   337  		return errors.NotValidf("ParentName %q on non-host machine %q", args.ParentName, hostMachineID)
   338  	}
   339  
   340  	err = m.verifyHostMachineParentDeviceExistsAndIsABridgeDevice(hostMachineID, parentDeviceName)
   341  	return errors.Trace(err)
   342  }
   343  
   344  func parseLinkLayerDeviceParentNameAsGlobalKey(parentName string) (hostMachineID, parentDeviceName string, err error) {
   345  	hostMachineID, parentDeviceName, canBeGlobalKey := parseLinkLayerDeviceGlobalKey(parentName)
   346  	if !canBeGlobalKey {
   347  		return "", "", nil
   348  	} else if hostMachineID == "" {
   349  		return "", "", errors.NotValidf("ParentName %q format", parentName)
   350  	}
   351  	return hostMachineID, parentDeviceName, nil
   352  }
   353  
   354  func (m *Machine) verifyHostMachineParentDeviceExistsAndIsABridgeDevice(hostMachineID, parentDeviceName string) error {
   355  	hostMachine, err := m.st.Machine(hostMachineID)
   356  	if errors.IsNotFound(err) || err == nil && hostMachine.Life() != Alive {
   357  		return errors.Errorf("host machine %q of parent device %q not found or not alive", hostMachineID, parentDeviceName)
   358  	} else if err != nil {
   359  		return errors.Trace(err)
   360  	}
   361  
   362  	parentDevice, err := hostMachine.LinkLayerDevice(parentDeviceName)
   363  	if errors.IsNotFound(err) {
   364  		return errors.NotFoundf("parent device %q on host machine %q", parentDeviceName, hostMachineID)
   365  	} else if err != nil {
   366  		return errors.Trace(err)
   367  	}
   368  
   369  	if parentDevice.Type() != BridgeDevice {
   370  		errorMessage := fmt.Sprintf(
   371  			"parent device %q on host machine %q must be of type %q, not type %q",
   372  			parentDeviceName, hostMachineID, BridgeDevice, parentDevice.Type(),
   373  		)
   374  		return errors.NewNotValid(nil, errorMessage)
   375  	}
   376  	return nil
   377  }
   378  
   379  func (m *Machine) validateParentDeviceNameWhenNotAGlobalKey(args *LinkLayerDeviceArgs) error {
   380  	if !IsValidLinkLayerDeviceName(args.ParentName) {
   381  		logger.Warningf(
   382  			"parent link-layer device %q on machine %q has invalid name (using anyway)",
   383  			args.ParentName, m.Id(),
   384  		)
   385  	}
   386  	if args.Name == args.ParentName {
   387  		return errors.NewNotValid(nil, "Name and ParentName must be different")
   388  	}
   389  	if err := m.verifyParentDeviceExists(args.ParentName); err != nil {
   390  		return errors.Trace(err)
   391  	}
   392  	return nil
   393  }
   394  
   395  func (m *Machine) verifyParentDeviceExists(parentName string) error {
   396  	if _, err := m.LinkLayerDevice(parentName); err != nil {
   397  		return errors.Trace(err)
   398  	}
   399  	return nil
   400  }
   401  
   402  func (m *Machine) newLinkLayerDeviceDocFromArgs(args *LinkLayerDeviceArgs) *linkLayerDeviceDoc {
   403  	linkLayerDeviceDocID := m.linkLayerDeviceDocIDFromName(args.Name)
   404  
   405  	providerID := string(args.ProviderID)
   406  	modelUUID := m.st.ModelUUID()
   407  
   408  	return &linkLayerDeviceDoc{
   409  		DocID:       linkLayerDeviceDocID,
   410  		Name:        args.Name,
   411  		ModelUUID:   modelUUID,
   412  		MTU:         args.MTU,
   413  		ProviderID:  providerID,
   414  		MachineID:   m.doc.Id,
   415  		Type:        args.Type,
   416  		MACAddress:  args.MACAddress,
   417  		IsAutoStart: args.IsAutoStart,
   418  		IsUp:        args.IsUp,
   419  		ParentName:  args.ParentName,
   420  	}
   421  }
   422  
   423  func (m *Machine) isStillAlive() error {
   424  	if machineAlive, err := isAlive(m.st, machinesC, m.doc.Id); err != nil {
   425  		return errors.Trace(err)
   426  	} else if !machineAlive {
   427  		return errors.Errorf("machine not found or not alive")
   428  	}
   429  	return nil
   430  }
   431  
   432  func (m *Machine) assertAliveOp() txn.Op {
   433  	return txn.Op{
   434  		C:      machinesC,
   435  		Id:     m.doc.Id,
   436  		Assert: isAliveDoc,
   437  	}
   438  }
   439  
   440  func (m *Machine) setDevicesFromDocsOps(newDocs []linkLayerDeviceDoc) ([]txn.Op, error) {
   441  	devices, closer := m.st.getCollection(linkLayerDevicesC)
   442  	defer closer()
   443  
   444  	var ops []txn.Op
   445  	for _, newDoc := range newDocs {
   446  		var existingDoc linkLayerDeviceDoc
   447  		if err := devices.FindId(newDoc.DocID).One(&existingDoc); err == mgo.ErrNotFound {
   448  			// Device does not exist yet - insert it.
   449  			insertOps, err := m.insertLinkLayerDeviceOps(&newDoc)
   450  			if err != nil {
   451  				return nil, errors.Trace(err)
   452  			}
   453  			ops = append(ops, insertOps...)
   454  		} else if err == nil {
   455  			// Device already exists - update what's possible.
   456  			updateOps, err := m.updateLinkLayerDeviceOps(&existingDoc, &newDoc)
   457  			if err != nil {
   458  				return nil, errors.Trace(err)
   459  			}
   460  			ops = append(ops, updateOps...)
   461  		} else {
   462  			return nil, errors.Trace(err)
   463  		}
   464  	}
   465  	return ops, nil
   466  }
   467  
   468  func (m *Machine) insertLinkLayerDeviceOps(newDoc *linkLayerDeviceDoc) ([]txn.Op, error) {
   469  	modelUUID, linkLayerDeviceDocID := newDoc.ModelUUID, newDoc.DocID
   470  
   471  	var ops []txn.Op
   472  	if newDoc.ParentName != "" {
   473  		newParentDocID, err := m.parentDocIDFromDeviceDoc(newDoc)
   474  		if err != nil {
   475  			return nil, errors.Trace(err)
   476  		}
   477  		if newParentDocID != "" {
   478  			ops = append(ops, assertLinkLayerDeviceExistsOp(newParentDocID))
   479  			ops = append(ops, incrementDeviceNumChildrenOp(newParentDocID))
   480  		}
   481  	}
   482  	if newDoc.ProviderID != "" {
   483  		id := network.Id(newDoc.ProviderID)
   484  		ops = append(ops, m.st.networkEntityGlobalKeyOp("linklayerdevice", id))
   485  	}
   486  	return append(ops,
   487  		insertLinkLayerDeviceDocOp(newDoc),
   488  		insertLinkLayerDevicesRefsOp(modelUUID, linkLayerDeviceDocID),
   489  	), nil
   490  }
   491  
   492  func (m *Machine) parentDocIDFromDeviceDoc(doc *linkLayerDeviceDoc) (string, error) {
   493  	hostMachineID, parentName, err := parseLinkLayerDeviceParentNameAsGlobalKey(doc.ParentName)
   494  	if err != nil {
   495  		return "", errors.Trace(err)
   496  	}
   497  	if parentName == "" {
   498  		// doc.ParentName is not a global key, but on the same machine.
   499  		return m.linkLayerDeviceDocIDFromName(doc.ParentName), nil
   500  	}
   501  	// doc.ParentName is a global key, on a different host machine.
   502  	return m.st.docID(linkLayerDeviceGlobalKey(hostMachineID, parentName)), nil
   503  }
   504  
   505  func (m *Machine) updateLinkLayerDeviceOps(existingDoc, newDoc *linkLayerDeviceDoc) (ops []txn.Op, err error) {
   506  	var newParentDocID string
   507  	if newDoc.ParentName != "" {
   508  		newParentDocID, err = m.parentDocIDFromDeviceDoc(newDoc)
   509  		if err != nil {
   510  			return nil, errors.Trace(err)
   511  		}
   512  	}
   513  	var existingParentDocID string
   514  	if existingDoc.ParentName != "" {
   515  		existingParentDocID, err = m.parentDocIDFromDeviceDoc(existingDoc)
   516  		if err != nil {
   517  			return nil, errors.Trace(err)
   518  		}
   519  	}
   520  
   521  	if newParentDocID != "" && existingParentDocID != "" && newParentDocID != existingParentDocID {
   522  		ops = append(ops,
   523  			assertLinkLayerDeviceExistsOp(newParentDocID),
   524  			incrementDeviceNumChildrenOp(newParentDocID),
   525  			assertLinkLayerDeviceExistsOp(existingParentDocID),
   526  			decrementDeviceNumChildrenOp(existingParentDocID),
   527  		)
   528  	} else if newParentDocID != "" && existingParentDocID == "" {
   529  		ops = append(ops, assertLinkLayerDeviceExistsOp(newParentDocID))
   530  		ops = append(ops, incrementDeviceNumChildrenOp(newParentDocID))
   531  	} else if newParentDocID == "" && existingParentDocID != "" {
   532  		ops = append(ops, assertLinkLayerDeviceExistsOp(existingParentDocID))
   533  		ops = append(ops, decrementDeviceNumChildrenOp(existingParentDocID))
   534  	}
   535  	ops = append(ops, updateLinkLayerDeviceDocOp(existingDoc, newDoc))
   536  
   537  	if newDoc.ProviderID != "" {
   538  		if existingDoc.ProviderID != "" && existingDoc.ProviderID != newDoc.ProviderID {
   539  			return nil, errors.Errorf("cannot change ProviderID of link layer device %q", existingDoc.Name)
   540  		}
   541  		if existingDoc.ProviderID != newDoc.ProviderID {
   542  			// Need to insert the new provider id in providerIDsC
   543  			id := network.Id(newDoc.ProviderID)
   544  			ops = append(ops, m.st.networkEntityGlobalKeyOp("linklayerdevice", id))
   545  		}
   546  	}
   547  	return ops, nil
   548  }
   549  
   550  // LinkLayerDeviceAddress contains an IP address assigned to a link-layer
   551  // device.
   552  type LinkLayerDeviceAddress struct {
   553  	// DeviceName is the name of the link-layer device that has this address.
   554  	DeviceName string
   555  
   556  	// ConfigMethod is the method used to configure this address.
   557  	ConfigMethod AddressConfigMethod
   558  
   559  	// ProviderID is the provider-specific ID of the address. Empty when not
   560  	// supported. Cannot be changed once set to non-empty.
   561  	ProviderID network.Id
   562  
   563  	// CIDRAddress is the IP address assigned to the device, in CIDR format
   564  	// (e.g. 10.20.30.5/24 or fc00:1234::/64).
   565  	CIDRAddress string
   566  
   567  	// DNSServers contains a list of DNS nameservers to use, which can be empty.
   568  	DNSServers []string
   569  
   570  	// DNSSearchDomains contains a list of DNS domain names to qualify
   571  	// hostnames, and can be empty.
   572  	DNSSearchDomains []string
   573  
   574  	// GatewayAddress is the address of the gateway to use, which can be empty.
   575  	GatewayAddress string
   576  }
   577  
   578  // SetDevicesAddresses sets the addresses of all devices in devicesAddresses,
   579  // adding new or updating existing assignments as needed, in a single
   580  // transaction. ProviderID field can be empty if not supported by the provider,
   581  // but when set must be unique within the model. Errors are returned in the
   582  // following cases:
   583  // - Machine is no longer alive or is missing;
   584  // - Subnet inferred from any CIDRAddress field in args is known but no longer
   585  //   alive (no error reported if the CIDRAddress does not match a known subnet);
   586  // - Model no longer alive;
   587  // - errors.NotValidError, when any of the fields in args contain invalid values;
   588  // - errors.NotFoundError, when any DeviceName in args refers to unknown device;
   589  // - ErrProviderIDNotUnique, when one or more specified ProviderIDs are not unique.
   590  func (m *Machine) SetDevicesAddresses(devicesAddresses ...LinkLayerDeviceAddress) (err error) {
   591  	defer errors.DeferredAnnotatef(&err, "cannot set link-layer device addresses of machine %q", m.doc.Id)
   592  
   593  	if len(devicesAddresses) == 0 {
   594  		logger.Warningf("no device addresses to set")
   595  		return nil
   596  	}
   597  
   598  	buildTxn := func(attempt int) ([]txn.Op, error) {
   599  		newDocs, err := m.prepareToSetDevicesAddresses(devicesAddresses)
   600  		if err != nil {
   601  			return nil, errors.Trace(err)
   602  		}
   603  
   604  		if attempt > 0 {
   605  			if err := checkModelActive(m.st); err != nil {
   606  				return nil, errors.Trace(err)
   607  			}
   608  			if err := m.isStillAlive(); err != nil {
   609  				return nil, errors.Trace(err)
   610  			}
   611  			allIds, err := m.st.allProviderIDsForAddresses()
   612  			if err != nil {
   613  				return nil, errors.Trace(err)
   614  			}
   615  			for _, args := range devicesAddresses {
   616  				if allIds.Contains(string(args.ProviderID)) {
   617  					err := NewProviderIDNotUniqueError(args.ProviderID)
   618  					return nil, errors.Annotatef(err, "invalid address %q", args.CIDRAddress)
   619  				}
   620  			}
   621  		}
   622  
   623  		ops := []txn.Op{
   624  			assertModelActiveOp(m.st.ModelUUID()),
   625  			m.assertAliveOp(),
   626  		}
   627  
   628  		setAddressesOps, err := m.setDevicesAddressesFromDocsOps(newDocs)
   629  		if err != nil {
   630  			return nil, errors.Trace(err)
   631  		}
   632  		return append(ops, setAddressesOps...), nil
   633  	}
   634  	if err := m.st.run(buildTxn); err != nil {
   635  		return errors.Trace(err)
   636  	}
   637  	return nil
   638  }
   639  
   640  func (m *Machine) prepareToSetDevicesAddresses(devicesAddresses []LinkLayerDeviceAddress) ([]ipAddressDoc, error) {
   641  	var pendingDocs []ipAddressDoc
   642  	for _, args := range devicesAddresses {
   643  		newDoc, err := m.prepareOneSetDevicesAddresses(&args)
   644  		if err != nil {
   645  			return nil, errors.Trace(err)
   646  		}
   647  		pendingDocs = append(pendingDocs, *newDoc)
   648  	}
   649  	return pendingDocs, nil
   650  }
   651  
   652  func (m *Machine) prepareOneSetDevicesAddresses(args *LinkLayerDeviceAddress) (_ *ipAddressDoc, err error) {
   653  	defer errors.DeferredAnnotatef(&err, "invalid address %q", args.CIDRAddress)
   654  
   655  	if err := m.validateSetDevicesAddressesArgs(args); err != nil {
   656  		return nil, errors.Trace(err)
   657  	}
   658  	return m.newIPAddressDocFromArgs(args)
   659  }
   660  
   661  func (m *Machine) validateSetDevicesAddressesArgs(args *LinkLayerDeviceAddress) error {
   662  	if args.CIDRAddress == "" {
   663  		return errors.NotValidf("empty CIDRAddress")
   664  	}
   665  	if _, _, err := net.ParseCIDR(args.CIDRAddress); err != nil {
   666  		return errors.NewNotValid(err, "CIDRAddress")
   667  	}
   668  
   669  	if args.DeviceName == "" {
   670  		return errors.NotValidf("empty DeviceName")
   671  	}
   672  	if !IsValidLinkLayerDeviceName(args.DeviceName) {
   673  		logger.Warningf(
   674  			"address %q on machine %q has invalid device name %q (using anyway)",
   675  			args.CIDRAddress, m.Id(), args.DeviceName,
   676  		)
   677  	}
   678  	if err := m.verifyDeviceAlreadyExists(args.DeviceName); err != nil {
   679  		return errors.Trace(err)
   680  	}
   681  
   682  	if !IsValidAddressConfigMethod(string(args.ConfigMethod)) {
   683  		return errors.NotValidf("ConfigMethod %q", args.ConfigMethod)
   684  	}
   685  
   686  	if args.GatewayAddress != "" {
   687  		if ip := net.ParseIP(args.GatewayAddress); ip == nil {
   688  			return errors.NotValidf("GatewayAddress %q", args.GatewayAddress)
   689  		}
   690  	}
   691  
   692  	return nil
   693  }
   694  
   695  func (m *Machine) verifyDeviceAlreadyExists(deviceName string) error {
   696  	if _, err := m.LinkLayerDevice(deviceName); errors.IsNotFound(err) {
   697  		return errors.NotFoundf("DeviceName %q on machine %q", deviceName, m.Id())
   698  	} else if err != nil {
   699  		return errors.Trace(err)
   700  	}
   701  	return nil
   702  }
   703  
   704  func (m *Machine) newIPAddressDocFromArgs(args *LinkLayerDeviceAddress) (*ipAddressDoc, error) {
   705  	ip, ipNet, err := net.ParseCIDR(args.CIDRAddress)
   706  	if err != nil {
   707  		// We already validated CIDRAddress earlier, so this cannot happen in
   708  		// practice, but we handle it anyway.
   709  		return nil, errors.Trace(err)
   710  	}
   711  	addressValue := ip.String()
   712  	subnetCIDR := ipNet.String()
   713  	subnet, err := m.st.Subnet(subnetCIDR)
   714  	if errors.IsNotFound(err) {
   715  		logger.Infof(
   716  			"address %q on machine %q uses unknown or machine-local subnet %q",
   717  			addressValue, m.Id(), subnetCIDR,
   718  		)
   719  	} else if err != nil {
   720  		return nil, errors.Trace(err)
   721  	} else if err := m.verifySubnetAlive(subnet); err != nil {
   722  		return nil, errors.Trace(err)
   723  	}
   724  
   725  	globalKey := ipAddressGlobalKey(m.doc.Id, args.DeviceName, addressValue)
   726  	ipAddressDocID := m.st.docID(globalKey)
   727  	providerID := string(args.ProviderID)
   728  
   729  	modelUUID := m.st.ModelUUID()
   730  
   731  	newDoc := &ipAddressDoc{
   732  		DocID:            ipAddressDocID,
   733  		ModelUUID:        modelUUID,
   734  		ProviderID:       providerID,
   735  		DeviceName:       args.DeviceName,
   736  		MachineID:        m.doc.Id,
   737  		SubnetCIDR:       subnetCIDR,
   738  		ConfigMethod:     args.ConfigMethod,
   739  		Value:            addressValue,
   740  		DNSServers:       args.DNSServers,
   741  		DNSSearchDomains: args.DNSSearchDomains,
   742  		GatewayAddress:   args.GatewayAddress,
   743  	}
   744  	return newDoc, nil
   745  }
   746  
   747  func (m *Machine) verifySubnetAlive(subnet *Subnet) error {
   748  	if subnet.Life() != Alive {
   749  		return errors.Errorf("subnet %q is not alive", subnet.CIDR())
   750  	}
   751  	return nil
   752  }
   753  
   754  func (m *Machine) setDevicesAddressesFromDocsOps(newDocs []ipAddressDoc) ([]txn.Op, error) {
   755  	addresses, closer := m.st.getCollection(ipAddressesC)
   756  	defer closer()
   757  
   758  	var ops []txn.Op
   759  
   760  	for _, newDoc := range newDocs {
   761  		deviceDocID := m.linkLayerDeviceDocIDFromName(newDoc.DeviceName)
   762  		ops = append(ops, assertLinkLayerDeviceExistsOp(deviceDocID))
   763  
   764  		var existingDoc ipAddressDoc
   765  		err := addresses.FindId(newDoc.DocID).One(&existingDoc)
   766  		if err == mgo.ErrNotFound {
   767  			// Address does not exist yet - insert it.
   768  			ops = append(ops, insertIPAddressDocOp(&newDoc))
   769  			if newDoc.ProviderID != "" {
   770  				id := network.Id(newDoc.ProviderID)
   771  				ops = append(ops, m.st.networkEntityGlobalKeyOp("address", id))
   772  			}
   773  		} else if err == nil {
   774  			// Address already exists - update what's possible.
   775  			ops = append(ops, updateIPAddressDocOp(&existingDoc, &newDoc))
   776  			if newDoc.ProviderID != "" {
   777  				if existingDoc.ProviderID != "" && existingDoc.ProviderID != newDoc.ProviderID {
   778  					return nil, errors.Errorf("cannot change ProviderID of link address %q", existingDoc.Value)
   779  				}
   780  				if existingDoc.ProviderID != newDoc.ProviderID {
   781  					// Need to insert the new provider id in providerIDsC
   782  					id := network.Id(newDoc.ProviderID)
   783  					ops = append(ops, m.st.networkEntityGlobalKeyOp("address", id))
   784  				}
   785  			}
   786  		} else {
   787  			return nil, errors.Trace(err)
   788  		}
   789  
   790  		ops, err = m.maybeAssertSubnetAliveOps(&newDoc, ops)
   791  		if err != nil {
   792  			return nil, errors.Trace(err)
   793  		}
   794  	}
   795  	return ops, nil
   796  }
   797  
   798  func (m *Machine) maybeAssertSubnetAliveOps(newDoc *ipAddressDoc, opsSoFar []txn.Op) ([]txn.Op, error) {
   799  	subnet, err := m.st.Subnet(newDoc.SubnetCIDR)
   800  	if errors.IsNotFound(err) {
   801  		// Subnet is machine-local, no need to assert whether it's alive.
   802  		return opsSoFar, nil
   803  	} else if err != nil {
   804  		return nil, errors.Trace(err)
   805  	}
   806  	if err := m.verifySubnetAlive(subnet); err != nil {
   807  		return nil, errors.Trace(err)
   808  	}
   809  
   810  	// Subnet exists and is still alive, assert that is stays that way.
   811  	return append(opsSoFar, txn.Op{
   812  		C:      subnetsC,
   813  		Id:     m.st.docID(newDoc.SubnetCIDR),
   814  		Assert: isAliveDoc,
   815  	}), nil
   816  }
   817  
   818  // RemoveAllAddresses removes all assigned addresses to all devices of the
   819  // machine, in a single transaction. No error is returned when some or all of
   820  // the addresses were already removed.
   821  func (m *Machine) RemoveAllAddresses() error {
   822  	ops, err := m.removeAllAddressesOps()
   823  	if err != nil {
   824  		return errors.Trace(err)
   825  	}
   826  
   827  	return m.st.runTransaction(ops)
   828  }
   829  
   830  func (m *Machine) removeAllAddressesOps() ([]txn.Op, error) {
   831  	findQuery := findAddressesQuery(m.doc.Id, "")
   832  	return m.st.removeMatchingIPAddressesDocOps(findQuery)
   833  }
   834  
   835  // AllAddresses returns the all addresses assigned to all devices of the
   836  // machine.
   837  func (m *Machine) AllAddresses() ([]*Address, error) {
   838  	var allAddresses []*Address
   839  	callbackFunc := func(resultDoc *ipAddressDoc) {
   840  		allAddresses = append(allAddresses, newIPAddress(m.st, *resultDoc))
   841  	}
   842  
   843  	findQuery := findAddressesQuery(m.doc.Id, "")
   844  	if err := m.st.forEachIPAddressDoc(findQuery, callbackFunc); err != nil {
   845  		return nil, errors.Trace(err)
   846  	}
   847  	return allAddresses, nil
   848  }
   849  
   850  // SetParentLinkLayerDevicesBeforeTheirChildren splits the given devicesArgs
   851  // into multiple sets of args and calls SetLinkLayerDevices() for each set, such
   852  // that child devices are set only after their parents.
   853  func (m *Machine) SetParentLinkLayerDevicesBeforeTheirChildren(devicesArgs []LinkLayerDeviceArgs) error {
   854  	seenNames := set.NewStrings("") // sentinel for empty ParentName.
   855  	for {
   856  		argsToSet := []LinkLayerDeviceArgs{}
   857  		for _, args := range devicesArgs {
   858  			if seenNames.Contains(args.Name) {
   859  				// Already added earlier.
   860  				continue
   861  			}
   862  			if seenNames.Contains(args.ParentName) {
   863  				argsToSet = append(argsToSet, args)
   864  			}
   865  		}
   866  		if len(argsToSet) == 0 {
   867  			// We're done.
   868  			break
   869  		}
   870  		logger.Debugf("setting link-layer devices %+v", argsToSet)
   871  		if err := m.SetLinkLayerDevices(argsToSet...); IsProviderIDNotUniqueError(err) {
   872  			// FIXME: Make updating devices with unchanged ProviderID idempotent.
   873  			// FIXME: this obliterates the ProviderID of *all*
   874  			// devices if any *one* of them is not unique.
   875  			for i, args := range argsToSet {
   876  				args.ProviderID = ""
   877  				argsToSet[i] = args
   878  			}
   879  			if err := m.SetLinkLayerDevices(argsToSet...); err != nil {
   880  				return errors.Trace(err)
   881  			}
   882  		} else if err != nil {
   883  			return errors.Trace(err)
   884  		}
   885  		for _, args := range argsToSet {
   886  			seenNames.Add(args.Name)
   887  		}
   888  	}
   889  	return nil
   890  }
   891  
   892  // SetDevicesAddressesIdempotently calls SetDevicesAddresses() and if it fails
   893  // with ErrProviderIDNotUnique, retries the call with all ProviderID fields in
   894  // devicesAddresses set to empty.
   895  func (m *Machine) SetDevicesAddressesIdempotently(devicesAddresses []LinkLayerDeviceAddress) error {
   896  	if err := m.SetDevicesAddresses(devicesAddresses...); IsProviderIDNotUniqueError(err) {
   897  		// FIXME: Make updating addresses with unchanged ProviderID idempotent.
   898  		// FIXME: this obliterates the ProviderID of *all*
   899  		// addresses if any *one* of them is not unique.
   900  		for i, args := range devicesAddresses {
   901  			args.ProviderID = ""
   902  			devicesAddresses[i] = args
   903  		}
   904  		if err := m.SetDevicesAddresses(devicesAddresses...); err != nil {
   905  			return errors.Trace(err)
   906  		}
   907  	} else if err != nil {
   908  		return errors.Trace(err)
   909  	}
   910  	return nil
   911  }
   912  
   913  // SetContainerLinkLayerDevices sets the link-layer devices of the given
   914  // containerMachine, setting each device linked to the corresponding
   915  // BridgeDevice of the host machine m.
   916  func (m *Machine) SetContainerLinkLayerDevices(containerMachine *Machine) error {
   917  	allDevices, err := m.AllLinkLayerDevices()
   918  	if err != nil {
   919  		return errors.Annotate(err, "cannot get host machine devices")
   920  	}
   921  
   922  	bridgeDevicesByName := make(map[string]*LinkLayerDevice)
   923  	bridgeDeviceNames := make([]string, 0, len(allDevices))
   924  
   925  	for _, hostDevice := range allDevices {
   926  		deviceType, name := hostDevice.Type(), hostDevice.Name()
   927  		// Since the default bridges (for each container type) are
   928  		// machine-local, and there's neither a way (at least not yet) nor any
   929  		// point in allocating addresses from the (machine-local) subnets
   930  		// configured on those bridges, we need to ignore them below.
   931  		if deviceType == BridgeDevice {
   932  			switch name {
   933  			case container.DefaultLxdBridge, container.DefaultKvmBridge:
   934  				logger.Debugf("skipping host bridge %q", name)
   935  				continue
   936  			}
   937  			bridgeDevicesByName[name] = hostDevice
   938  			bridgeDeviceNames = append(bridgeDeviceNames, name)
   939  		}
   940  	}
   941  
   942  	sortedBridgeDeviceNames := network.NaturallySortDeviceNames(bridgeDeviceNames...)
   943  	logger.Debugf("using host machine %q bridge devices: %v", m.Id(), sortedBridgeDeviceNames)
   944  	containerDevicesArgs := make([]LinkLayerDeviceArgs, len(bridgeDeviceNames))
   945  
   946  	for i, hostBridgeName := range sortedBridgeDeviceNames {
   947  		hostBridge := bridgeDevicesByName[hostBridgeName]
   948  		containerDevicesArgs[i] = LinkLayerDeviceArgs{
   949  			Name:        fmt.Sprintf("eth%d", i),
   950  			Type:        EthernetDevice,
   951  			MACAddress:  generateMACAddress(),
   952  			MTU:         hostBridge.MTU(),
   953  			IsUp:        true,
   954  			IsAutoStart: true,
   955  			ParentName:  hostBridge.globalKey(),
   956  		}
   957  	}
   958  	logger.Debugf("prepared container %q network config: %+v", containerMachine.Id(), containerDevicesArgs)
   959  
   960  	if err := containerMachine.SetLinkLayerDevices(containerDevicesArgs...); err != nil {
   961  		return errors.Trace(err)
   962  	}
   963  
   964  	logger.Debugf("container %q network config set", containerMachine.Id())
   965  	return nil
   966  }
   967  
   968  // MACAddressTemplate is used to generate a unique MAC address for a
   969  // container. Every '%x' is replaced by a random hexadecimal digit,
   970  // while the rest is kept as-is.
   971  const macAddressTemplate = "00:16:3e:%02x:%02x:%02x"
   972  
   973  // generateMACAddress creates a random MAC address within the space defined by
   974  // macAddressTemplate above.
   975  //
   976  // TODO(dimitern): We should make a best effort to ensure the MAC address we
   977  // generate is unique at least within the current environment.
   978  func generateMACAddress() string {
   979  	digits := make([]interface{}, 3)
   980  	for i := range digits {
   981  		digits[i] = rand.Intn(256)
   982  	}
   983  	return fmt.Sprintf(macAddressTemplate, digits...)
   984  }