1
// Copyright 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
14
var ErrNoDNSName = errors.New("DNS name not allocated")
16
// An instance Id is a provider-specific identifier associated with an
17
// instance (physical or virtual machine allocated in the provider).
20
// Port identifies a network port number for a particular protocol.
26
func (p Port) String() string {
27
return fmt.Sprintf("%s:%d", p.Protocol, p.Number)
30
// Instance represents the the realization of a machine in state.
31
type Instance interface {
32
// Id returns a provider-generated identifier for the Instance.
35
// DNSName returns the DNS name for the instance.
36
// If the name is not yet allocated, it will return
37
// an ErrNoDNSName error.
38
DNSName() (string, error)
40
// WaitDNSName returns the DNS name for the instance,
41
// waiting until it is allocated if necessary.
42
// TODO: We may not need this in the interface any more. All
43
// implementations now delegate to environs.WaitDNSName.
44
WaitDNSName() (string, error)
46
// OpenPorts opens the given ports on the instance, which
47
// should have been started with the given machine id.
48
OpenPorts(machineId string, ports []Port) error
50
// ClosePorts closes the given ports on the instance, which
51
// should have been started with the given machine id.
52
ClosePorts(machineId string, ports []Port) error
54
// Ports returns the set of ports open on the instance, which
55
// should have been started with the given machine id.
56
// The ports are returned as sorted by state.SortPorts.
57
Ports(machineId string) ([]Port, error)
60
// HardwareCharacteristics represents the characteristics of the instance (if known).
61
// Attributes that are nil are unknown or not supported.
62
type HardwareCharacteristics struct {
69
func uintStr(i uint64) string {
73
return fmt.Sprintf("%d", i)
76
func (hc HardwareCharacteristics) String() string {
79
strs = append(strs, "arch="+*hc.Arch)
81
if hc.CpuCores != nil {
82
strs = append(strs, "cpu-cores="+uintStr(*hc.CpuCores))
84
if hc.CpuPower != nil {
85
strs = append(strs, "cpu-power="+uintStr(*hc.CpuPower))
92
strs = append(strs, "mem="+s)
94
return strings.Join(strs, " ")
97
// MustParseHardware constructs a HardwareCharacteristics from the supplied arguments,
98
// as Parse, but panics on failure.
99
func MustParseHardware(args ...string) HardwareCharacteristics {
100
hc, err := ParseHardware(args...)
107
// ParseHardware constructs a HardwareCharacteristics from the supplied arguments,
108
// each of which must contain only spaces and name=value pairs. If any
109
// name is specified more than once, an error is returned.
110
func ParseHardware(args ...string) (HardwareCharacteristics, error) {
111
hc := HardwareCharacteristics{}
112
for _, arg := range args {
113
raws := strings.Split(strings.TrimSpace(arg), " ")
114
for _, raw := range raws {
118
if err := hc.setRaw(raw); err != nil {
119
return HardwareCharacteristics{}, err
126
// setRaw interprets a name=value string and sets the supplied value.
127
func (hc *HardwareCharacteristics) setRaw(raw string) error {
128
eq := strings.Index(raw, "=")
130
return fmt.Errorf("malformed characteristic %q", raw)
132
name, str := raw[:eq], raw[eq+1:]
136
err = hc.setArch(str)
138
err = hc.setCpuCores(str)
140
err = hc.setCpuPower(str)
144
return fmt.Errorf("unknown characteristic %q", name)
147
return fmt.Errorf("bad %q characteristic: %v", name, err)
152
func (hc *HardwareCharacteristics) setArch(str string) error {
154
return fmt.Errorf("already set")
158
case "amd64", "i386", "arm":
160
return fmt.Errorf("%q not recognized", str)
166
func (hc *HardwareCharacteristics) setCpuCores(str string) (err error) {
167
if hc.CpuCores != nil {
168
return fmt.Errorf("already set")
170
hc.CpuCores, err = parseUint64(str)
174
func (hc *HardwareCharacteristics) setCpuPower(str string) (err error) {
175
if hc.CpuPower != nil {
176
return fmt.Errorf("already set")
178
hc.CpuPower, err = parseUint64(str)
182
func (hc *HardwareCharacteristics) setMem(str string) error {
184
return fmt.Errorf("already set")
189
if m, ok := mbSuffixes[str[len(str)-1:]]; ok {
190
str = str[:len(str)-1]
193
val, err := strconv.ParseFloat(str, 64)
194
if err != nil || val < 0 {
195
return fmt.Errorf("must be a non-negative float with optional M/G/T/P suffix")
198
value = uint64(math.Ceil(val))
204
func parseUint64(str string) (*uint64, error) {
207
if val, err := strconv.ParseUint(str, 10, 64); err != nil {
208
return nil, fmt.Errorf("must be a non-negative integer")
216
var mbSuffixes = map[string]float64{
220
"P": 1024 * 1024 * 1024,