launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/provider/maas/instance.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package maas
     5  
     6  import (
     7  	"fmt"
     8  	"sync"
     9  
    10  	"launchpad.net/gomaasapi"
    11  
    12  	"launchpad.net/juju-core/instance"
    13  	"launchpad.net/juju-core/provider/common"
    14  )
    15  
    16  type maasInstance struct {
    17  	environ *maasEnviron
    18  
    19  	mu         sync.Mutex
    20  	maasObject *gomaasapi.MAASObject
    21  }
    22  
    23  var _ instance.Instance = (*maasInstance)(nil)
    24  
    25  func (mi *maasInstance) String() string {
    26  	hostname, err := mi.DNSName()
    27  	if err != nil {
    28  		// This is meant to be impossible, but be paranoid.
    29  		hostname = fmt.Sprintf("<DNSName failed: %q>", err)
    30  	}
    31  	return fmt.Sprintf("%s:%s", hostname, mi.Id())
    32  }
    33  
    34  func (mi *maasInstance) Id() instance.Id {
    35  	return maasObjectId(mi.getMaasObject())
    36  }
    37  
    38  func maasObjectId(maasObject *gomaasapi.MAASObject) instance.Id {
    39  	// Use the node's 'resource_uri' value.
    40  	return instance.Id(maasObject.URI().String())
    41  }
    42  
    43  func (mi *maasInstance) Status() string {
    44  	// MAAS does not track node status once they're allocated.
    45  	// Since any instance that juju knows about will be an
    46  	// allocated one, it doesn't make sense to report any
    47  	// state unless we obtain it through some means other than
    48  	// through the MAAS API.
    49  	return ""
    50  }
    51  
    52  // Refresh refreshes the instance with the most up-to-date information
    53  // from the MAAS server.
    54  func (mi *maasInstance) Refresh() error {
    55  	mi.mu.Lock()
    56  	defer mi.mu.Unlock()
    57  	insts, err := mi.environ.Instances([]instance.Id{maasObjectId(mi.maasObject)})
    58  	if err != nil {
    59  		return err
    60  	}
    61  	mi.maasObject = insts[0].(*maasInstance).maasObject
    62  	return nil
    63  }
    64  
    65  func (mi *maasInstance) getMaasObject() *gomaasapi.MAASObject {
    66  	mi.mu.Lock()
    67  	defer mi.mu.Unlock()
    68  	return mi.maasObject
    69  }
    70  
    71  func (mi *maasInstance) Addresses() ([]instance.Address, error) {
    72  	name, err := mi.DNSName()
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	host := instance.Address{name, instance.HostName, "", instance.NetworkPublic}
    77  	addrs := []instance.Address{host}
    78  
    79  	ips, err := mi.ipAddresses()
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	for _, ip := range ips {
    85  		a := instance.Address{ip, instance.DeriveAddressType(ip), "", instance.NetworkUnknown}
    86  		addrs = append(addrs, a)
    87  	}
    88  
    89  	return addrs, nil
    90  }
    91  
    92  func (mi *maasInstance) ipAddresses() ([]string, error) {
    93  	// we have to do this the hard way, since maasObject doesn't have this built-in yet
    94  	addressArray := mi.getMaasObject().GetMap()["ip_addresses"]
    95  	if addressArray.IsNil() {
    96  		// Older MAAS versions do not return ip_addresses.
    97  		return nil, nil
    98  	}
    99  	objs, err := addressArray.GetArray()
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	ips := make([]string, len(objs))
   104  	for i, obj := range objs {
   105  		s, err := obj.GetString()
   106  		if err != nil {
   107  			return nil, err
   108  		}
   109  		ips[i] = s
   110  	}
   111  	return ips, nil
   112  }
   113  
   114  func (mi *maasInstance) DNSName() (string, error) {
   115  	// A MAAS instance has its DNS name immediately.
   116  	return mi.getMaasObject().GetField("hostname")
   117  }
   118  
   119  func (mi *maasInstance) WaitDNSName() (string, error) {
   120  	return common.WaitDNSName(mi)
   121  }
   122  
   123  // MAAS does not do firewalling so these port methods do nothing.
   124  func (mi *maasInstance) OpenPorts(machineId string, ports []instance.Port) error {
   125  	logger.Debugf("unimplemented OpenPorts() called")
   126  	return nil
   127  }
   128  
   129  func (mi *maasInstance) ClosePorts(machineId string, ports []instance.Port) error {
   130  	logger.Debugf("unimplemented ClosePorts() called")
   131  	return nil
   132  }
   133  
   134  func (mi *maasInstance) Ports(machineId string) ([]instance.Port, error) {
   135  	logger.Debugf("unimplemented Ports() called")
   136  	return []instance.Port{}, nil
   137  }