~rogpeppe/juju-core/azure

« back to all changes in this revision

Viewing changes to instance/instance.go

  • Committer: Gustavo Niemeyer
  • Date: 2011-09-26 14:48:45 UTC
  • mto: This revision was merged to the branch mainline in revision 34.
  • Revision ID: gustavo@niemeyer.net-20110926144845-atwp3u6blqngmhel
Bootstrapping store package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright 2013 Canonical Ltd.
2
 
// Licensed under the AGPLv3, see LICENCE file for details.
3
 
 
4
 
package instance
5
 
 
6
 
import (
7
 
        "errors"
8
 
        "fmt"
9
 
        "math"
10
 
        "strconv"
11
 
        "strings"
12
 
)
13
 
 
14
 
var ErrNoDNSName = errors.New("DNS name not allocated")
15
 
 
16
 
// An instance Id is a provider-specific identifier associated with an
17
 
// instance (physical or virtual machine allocated in the provider).
18
 
type Id string
19
 
 
20
 
// Port identifies a network port number for a particular protocol.
21
 
type Port struct {
22
 
        Protocol string
23
 
        Number   int
24
 
}
25
 
 
26
 
func (p Port) String() string {
27
 
        return fmt.Sprintf("%s:%d", p.Protocol, p.Number)
28
 
}
29
 
 
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.
33
 
        Id() Id
34
 
 
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)
39
 
 
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)
45
 
 
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
49
 
 
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
53
 
 
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)
58
 
}
59
 
 
60
 
// HardwareCharacteristics represents the characteristics of the instance (if known).
61
 
// Attributes that are nil are unknown or not supported.
62
 
type HardwareCharacteristics struct {
63
 
        Arch     *string
64
 
        Mem      *uint64
65
 
        CpuCores *uint64
66
 
        CpuPower *uint64
67
 
}
68
 
 
69
 
func uintStr(i uint64) string {
70
 
        if i == 0 {
71
 
                return ""
72
 
        }
73
 
        return fmt.Sprintf("%d", i)
74
 
}
75
 
 
76
 
func (hc HardwareCharacteristics) String() string {
77
 
        var strs []string
78
 
        if hc.Arch != nil {
79
 
                strs = append(strs, "arch="+*hc.Arch)
80
 
        }
81
 
        if hc.CpuCores != nil {
82
 
                strs = append(strs, "cpu-cores="+uintStr(*hc.CpuCores))
83
 
        }
84
 
        if hc.CpuPower != nil {
85
 
                strs = append(strs, "cpu-power="+uintStr(*hc.CpuPower))
86
 
        }
87
 
        if hc.Mem != nil {
88
 
                s := uintStr(*hc.Mem)
89
 
                if s != "" {
90
 
                        s += "M"
91
 
                }
92
 
                strs = append(strs, "mem="+s)
93
 
        }
94
 
        return strings.Join(strs, " ")
95
 
}
96
 
 
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...)
101
 
        if err != nil {
102
 
                panic(err)
103
 
        }
104
 
        return hc
105
 
}
106
 
 
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 {
115
 
                        if raw == "" {
116
 
                                continue
117
 
                        }
118
 
                        if err := hc.setRaw(raw); err != nil {
119
 
                                return HardwareCharacteristics{}, err
120
 
                        }
121
 
                }
122
 
        }
123
 
        return hc, nil
124
 
}
125
 
 
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, "=")
129
 
        if eq <= 0 {
130
 
                return fmt.Errorf("malformed characteristic %q", raw)
131
 
        }
132
 
        name, str := raw[:eq], raw[eq+1:]
133
 
        var err error
134
 
        switch name {
135
 
        case "arch":
136
 
                err = hc.setArch(str)
137
 
        case "cpu-cores":
138
 
                err = hc.setCpuCores(str)
139
 
        case "cpu-power":
140
 
                err = hc.setCpuPower(str)
141
 
        case "mem":
142
 
                err = hc.setMem(str)
143
 
        default:
144
 
                return fmt.Errorf("unknown characteristic %q", name)
145
 
        }
146
 
        if err != nil {
147
 
                return fmt.Errorf("bad %q characteristic: %v", name, err)
148
 
        }
149
 
        return nil
150
 
}
151
 
 
152
 
func (hc *HardwareCharacteristics) setArch(str string) error {
153
 
        if hc.Arch != nil {
154
 
                return fmt.Errorf("already set")
155
 
        }
156
 
        switch str {
157
 
        case "":
158
 
        case "amd64", "i386", "arm":
159
 
        default:
160
 
                return fmt.Errorf("%q not recognized", str)
161
 
        }
162
 
        hc.Arch = &str
163
 
        return nil
164
 
}
165
 
 
166
 
func (hc *HardwareCharacteristics) setCpuCores(str string) (err error) {
167
 
        if hc.CpuCores != nil {
168
 
                return fmt.Errorf("already set")
169
 
        }
170
 
        hc.CpuCores, err = parseUint64(str)
171
 
        return
172
 
}
173
 
 
174
 
func (hc *HardwareCharacteristics) setCpuPower(str string) (err error) {
175
 
        if hc.CpuPower != nil {
176
 
                return fmt.Errorf("already set")
177
 
        }
178
 
        hc.CpuPower, err = parseUint64(str)
179
 
        return
180
 
}
181
 
 
182
 
func (hc *HardwareCharacteristics) setMem(str string) error {
183
 
        if hc.Mem != nil {
184
 
                return fmt.Errorf("already set")
185
 
        }
186
 
        var value uint64
187
 
        if str != "" {
188
 
                mult := 1.0
189
 
                if m, ok := mbSuffixes[str[len(str)-1:]]; ok {
190
 
                        str = str[:len(str)-1]
191
 
                        mult = m
192
 
                }
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")
196
 
                }
197
 
                val *= mult
198
 
                value = uint64(math.Ceil(val))
199
 
        }
200
 
        hc.Mem = &value
201
 
        return nil
202
 
}
203
 
 
204
 
func parseUint64(str string) (*uint64, error) {
205
 
        var value uint64
206
 
        if str != "" {
207
 
                if val, err := strconv.ParseUint(str, 10, 64); err != nil {
208
 
                        return nil, fmt.Errorf("must be a non-negative integer")
209
 
                } else {
210
 
                        value = uint64(val)
211
 
                }
212
 
        }
213
 
        return &value, nil
214
 
}
215
 
 
216
 
var mbSuffixes = map[string]float64{
217
 
        "M": 1,
218
 
        "G": 1024,
219
 
        "T": 1024 * 1024,
220
 
        "P": 1024 * 1024 * 1024,
221
 
}