github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/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  	"github.com/juju/names"
    11  
    12  	"github.com/juju/juju/agent"
    13  	"github.com/juju/juju/api/machiner"
    14  	"github.com/juju/juju/api/watcher"
    15  	"github.com/juju/juju/apiserver/params"
    16  	"github.com/juju/juju/network"
    17  	"github.com/juju/juju/worker"
    18  )
    19  
    20  var logger = loggo.GetLogger("juju.worker.machiner")
    21  
    22  // Machiner is responsible for a machine agent's lifecycle.
    23  type Machiner struct {
    24  	st      *machiner.State
    25  	tag     names.MachineTag
    26  	machine *machiner.Machine
    27  }
    28  
    29  // NewMachiner returns a Worker that will wait for the identified machine
    30  // to become Dying and make it Dead; or until the machine becomes Dead by
    31  // other means.
    32  func NewMachiner(st *machiner.State, agentConfig agent.Config) worker.Worker {
    33  	// TODO(dfc) clearly agentConfig.Tag() can _only_ return a machine tag
    34  	mr := &Machiner{st: st, tag: agentConfig.Tag().(names.MachineTag)}
    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, 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, 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, fmt.Errorf("%s failed to set status started: %v", mr.tag, err)
    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 err
    70  	}
    71  	var hostAddresses []network.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  		address := network.NewAddress(ip.String(), network.ScopeUnknown)
    83  		// Filter out link-local addresses as we cannot reliably use them.
    84  		if address.Scope == network.ScopeLinkLocal {
    85  			continue
    86  		}
    87  		hostAddresses = append(hostAddresses, address)
    88  	}
    89  	if len(hostAddresses) == 0 {
    90  		return nil
    91  	}
    92  	logger.Infof("setting addresses for %v to %q", m.Tag(), hostAddresses)
    93  	return m.SetMachineAddresses(hostAddresses)
    94  }
    95  
    96  func (mr *Machiner) Handle() error {
    97  	if err := mr.machine.Refresh(); params.IsCodeNotFoundOrCodeUnauthorized(err) {
    98  		return worker.ErrTerminateAgent
    99  	} else if err != nil {
   100  		return err
   101  	}
   102  	if mr.machine.Life() == params.Alive {
   103  		return nil
   104  	}
   105  	logger.Debugf("%q is now %s", mr.tag, mr.machine.Life())
   106  	if err := mr.machine.SetStatus(params.StatusStopped, "", nil); err != nil {
   107  		return fmt.Errorf("%s failed to set status stopped: %v", mr.tag, err)
   108  	}
   109  
   110  	// If the machine is Dying, it has no units,
   111  	// and can be safely set to Dead.
   112  	if err := mr.machine.EnsureDead(); err != nil {
   113  		return fmt.Errorf("%s failed to set machine to dead: %v", mr.tag, err)
   114  	}
   115  	return worker.ErrTerminateAgent
   116  }
   117  
   118  func (mr *Machiner) TearDown() error {
   119  	// Nothing to do here.
   120  	return nil
   121  }