OLD | NEW |
1 // Copyright 2013 Canonical Ltd. | 1 // Copyright 2013 Canonical Ltd. |
2 // Licensed under the AGPLv3, see LICENCE file for details. | 2 // Licensed under the AGPLv3, see LICENCE file for details. |
3 | 3 |
4 package maas | 4 package maas |
5 | 5 |
6 import ( | 6 import ( |
7 "encoding/base64" | 7 "encoding/base64" |
8 "encoding/xml" | 8 "encoding/xml" |
9 "fmt" | 9 "fmt" |
10 "net" | 10 "net" |
(...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 args.MachineConfig.ExcludeNetworks, | 427 args.MachineConfig.ExcludeNetworks, |
428 args.Tools) | 428 args.Tools) |
429 if err != nil { | 429 if err != nil { |
430 return nil, nil, nil, fmt.Errorf("cannot run instances: %v", err
) | 430 return nil, nil, nil, fmt.Errorf("cannot run instances: %v", err
) |
431 } else { | 431 } else { |
432 inst = &maasInstance{maasObject: &node, environ: environ} | 432 inst = &maasInstance{maasObject: &node, environ: environ} |
433 args.MachineConfig.Tools = tools | 433 args.MachineConfig.Tools = tools |
434 } | 434 } |
435 defer func() { | 435 defer func() { |
436 if err != nil { | 436 if err != nil { |
437 » » » if err := environ.releaseInstance(inst); err != nil { | 437 » » » if err := environ.StopInstances(inst.Id()); err != nil { |
438 logger.Errorf("error releasing failed instance:
%v", err) | 438 logger.Errorf("error releasing failed instance:
%v", err) |
439 } | 439 } |
440 } | 440 } |
441 }() | 441 }() |
442 var networkInfo []network.Info | 442 var networkInfo []network.Info |
443 if args.MachineConfig.HasNetworks() { | 443 if args.MachineConfig.HasNetworks() { |
444 networkInfo, err = environ.setupNetworks(inst) | 444 networkInfo, err = environ.setupNetworks(inst) |
445 if err != nil { | 445 if err != nil { |
446 return nil, nil, nil, err | 446 return nil, nil, nil, err |
447 } | 447 } |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 // its parent interface was brought up. | 539 // its parent interface was brought up. |
540 script("vconfig add %s %d", info.InterfaceName, info.VLA
NTag) | 540 script("vconfig add %s %d", info.InterfaceName, info.VLA
NTag) |
541 vlan := fmt.Sprintf("%s.%d", info.InterfaceName, info.VL
ANTag) | 541 vlan := fmt.Sprintf("%s.%d", info.InterfaceName, info.VL
ANTag) |
542 script(ifaceConfig, vlan, vlan) | 542 script(ifaceConfig, vlan, vlan) |
543 script("ifup %s", vlan) | 543 script("ifup %s", vlan) |
544 } | 544 } |
545 } | 545 } |
546 } | 546 } |
547 | 547 |
548 // StopInstances is specified in the InstanceBroker interface. | 548 // StopInstances is specified in the InstanceBroker interface. |
549 func (environ *maasEnviron) StopInstances(instances []instance.Instance) error { | 549 func (environ *maasEnviron) StopInstances(ids ...instance.Id) error { |
550 // Shortcut to exit quickly if 'instances' is an empty slice or nil. | 550 // Shortcut to exit quickly if 'instances' is an empty slice or nil. |
551 » if len(instances) == 0 { | 551 » if len(ids) == 0 { |
552 return nil | 552 return nil |
553 } | 553 } |
554 » // Tell MAAS to release each of the instances. If there are errors, | 554 » // TODO(axw) 2014-05-13 #1319016 |
555 » // return only the first one (but release all instances regardless). | 555 » // Nodes that have been removed out of band will cause |
556 » // Note that releasing instances also turns them off. | 556 » // the release call to fail. We should parse the error |
557 » var firstErr error | 557 » // returned from MAAS and retry, or otherwise request |
558 » for _, instance := range instances { | 558 » // an enhancement to MAAS to ignore unknown node IDs. |
559 » » err := environ.releaseInstance(instance) | 559 » nodes := environ.getMAASClient().GetSubObject("nodes") |
560 » » if firstErr == nil { | 560 » _, err := nodes.CallPost("release", getSystemIdValues("nodes", ids)) |
561 » » » firstErr = err | |
562 » » } | |
563 » } | |
564 » return firstErr | |
565 } | |
566 | |
567 // releaseInstance releases a single instance. | |
568 func (environ *maasEnviron) releaseInstance(inst instance.Instance) error { | |
569 » maasInst := inst.(*maasInstance) | |
570 » maasObj := maasInst.maasObject | |
571 » _, err := maasObj.CallPost("release", nil) | |
572 » if err != nil { | |
573 » » logger.Debugf("error releasing instance %v", maasInst) | |
574 » } | |
575 return err | 561 return err |
576 } | 562 } |
577 | 563 |
578 // instances calls the MAAS API to list nodes. The "ids" slice is a filter for | 564 // instances calls the MAAS API to list nodes. The "ids" slice is a filter for |
579 // specific instance IDs. Due to how this works in the HTTP API, an empty | 565 // specific instance IDs. Due to how this works in the HTTP API, an empty |
580 // "ids" matches all instances (not none as you might expect). | 566 // "ids" matches all instances (not none as you might expect). |
581 func (environ *maasEnviron) instances(ids []instance.Id) ([]instance.Instance, e
rror) { | 567 func (environ *maasEnviron) instances(ids []instance.Id) ([]instance.Instance, e
rror) { |
582 nodeListing := environ.getMAASClient().GetSubObject("nodes") | 568 nodeListing := environ.getMAASClient().GetSubObject("nodes") |
583 » filter := getSystemIdValues(ids) | 569 » filter := getSystemIdValues("id", ids) |
584 filter.Add("agent_name", environ.ecfg().maasAgentName()) | 570 filter.Add("agent_name", environ.ecfg().maasAgentName()) |
585 listNodeObjects, err := nodeListing.CallGet("list", filter) | 571 listNodeObjects, err := nodeListing.CallGet("list", filter) |
586 if err != nil { | 572 if err != nil { |
587 return nil, err | 573 return nil, err |
588 } | 574 } |
589 listNodes, err := listNodeObjects.GetArray() | 575 listNodes, err := listNodeObjects.GetArray() |
590 if err != nil { | 576 if err != nil { |
591 return nil, err | 577 return nil, err |
592 } | 578 } |
593 instances := make([]instance.Instance, len(listNodes)) | 579 instances := make([]instance.Instance, len(listNodes)) |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 for _, node := range nodes { | 839 for _, node := range nodes { |
854 if strings.HasPrefix(node.Id, "network") { | 840 if strings.HasPrefix(node.Id, "network") { |
855 interfaces[node.Serial] = node.LogicalName | 841 interfaces[node.Serial] = node.LogicalName |
856 } | 842 } |
857 processNodes(node.Children) | 843 processNodes(node.Children) |
858 } | 844 } |
859 } | 845 } |
860 processNodes(lshw.Nodes) | 846 processNodes(lshw.Nodes) |
861 return interfaces, nil | 847 return interfaces, nil |
862 } | 848 } |
OLD | NEW |