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