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 }