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