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 }