github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/worker/machiner/machiner.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  package machiner
     4  
     5  import (
     6  	"fmt"
     7  	"net"
     8  
     9  	"github.com/juju/loggo"
    10  
    11  	"github.com/juju/juju/agent"
    12  	"github.com/juju/juju/instance"
    13  	"github.com/juju/juju/state/api/machiner"
    14  	"github.com/juju/juju/state/api/params"
    15  	"github.com/juju/juju/state/api/watcher"
    16  	"github.com/juju/juju/worker"
    17  )
    18  
    19  var logger = loggo.GetLogger("juju.worker.machiner")
    20  
    21  // Machiner is responsible for a machine agent's lifecycle.
    22  type Machiner struct {
    23  	st      *machiner.State
    24  	tag     string
    25  	machine *machiner.Machine
    26  }
    27  
    28  // NewMachiner returns a Worker that will wait for the identified machine
    29  // to become Dying and make it Dead; or until the machine becomes Dead by
    30  // other means.
    31  func NewMachiner(st *machiner.State, agentConfig agent.Config) worker.Worker {
    32  	mr := &Machiner{st: st, tag: agentConfig.Tag()}
    33  	return worker.NewNotifyWorker(mr)
    34  }
    35  
    36  func (mr *Machiner) SetUp() (watcher.NotifyWatcher, error) {
    37  	// Find which machine we're responsible for.
    38  	m, err := mr.st.Machine(mr.tag)
    39  	if params.IsCodeNotFoundOrCodeUnauthorized(err) {
    40  		return nil, worker.ErrTerminateAgent
    41  	} else if err != nil {
    42  		return nil, err
    43  	}
    44  	mr.machine = m
    45  
    46  	// Set the addresses in state to the host's addresses.
    47  	if err := setMachineAddresses(m); err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	// Mark the machine as started and log it.
    52  	if err := m.SetStatus(params.StatusStarted, "", nil); err != nil {
    53  		return nil, fmt.Errorf("%s failed to set status started: %v", mr.tag, err)
    54  	}
    55  	logger.Infof("%q started", mr.tag)
    56  
    57  	return m.Watch()
    58  }
    59  
    60  var interfaceAddrs = net.InterfaceAddrs
    61  
    62  // setMachineAddresses sets the addresses for this machine to all of the
    63  // host's non-loopback interface IP addresses.
    64  func setMachineAddresses(m *machiner.Machine) error {
    65  	addrs, err := interfaceAddrs()
    66  	if err != nil {
    67  		return err
    68  	}
    69  	var hostAddresses []instance.Address
    70  	for _, addr := range addrs {
    71  		var ip net.IP
    72  		switch addr := addr.(type) {
    73  		case *net.IPAddr:
    74  			ip = addr.IP
    75  		case *net.IPNet:
    76  			ip = addr.IP
    77  		default:
    78  			continue
    79  		}
    80  		address := instance.NewAddress(ip.String(), instance.NetworkUnknown)
    81  		hostAddresses = append(hostAddresses, address)
    82  	}
    83  	if len(hostAddresses) == 0 {
    84  		return nil
    85  	}
    86  	logger.Infof("setting addresses for %v to %q", m.Tag(), hostAddresses)
    87  	return m.SetMachineAddresses(hostAddresses)
    88  }
    89  
    90  func (mr *Machiner) Handle() error {
    91  	if err := mr.machine.Refresh(); params.IsCodeNotFoundOrCodeUnauthorized(err) {
    92  		return worker.ErrTerminateAgent
    93  	} else if err != nil {
    94  		return err
    95  	}
    96  	if mr.machine.Life() == params.Alive {
    97  		return nil
    98  	}
    99  	logger.Debugf("%q is now %s", mr.tag, mr.machine.Life())
   100  	if err := mr.machine.SetStatus(params.StatusStopped, "", nil); err != nil {
   101  		return fmt.Errorf("%s failed to set status stopped: %v", mr.tag, err)
   102  	}
   103  
   104  	// If the machine is Dying, it has no units,
   105  	// and can be safely set to Dead.
   106  	if err := mr.machine.EnsureDead(); err != nil {
   107  		return fmt.Errorf("%s failed to set machine to dead: %v", mr.tag, err)
   108  	}
   109  	return worker.ErrTerminateAgent
   110  }
   111  
   112  func (mr *Machiner) TearDown() error {
   113  	// Nothing to do here.
   114  	return nil
   115  }