1
// Copyright 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
12
"github.com/juju/utils/arch"
14
"github.com/juju/juju/network"
15
"github.com/juju/juju/status"
18
// An instance Id is a provider-specific identifier associated with an
19
// instance (physical or virtual machine allocated in the provider).
22
// InstanceStatus represents the status for a provider instance.
23
type InstanceStatus struct {
28
// UnknownId can be used to explicitly specify the instance ID does not matter.
29
const UnknownId Id = ""
31
// Instance represents the the realization of a machine in state.
32
type Instance interface {
33
// Id returns a provider-generated identifier for the Instance.
36
// Status returns the provider-specific status for the instance.
37
Status() InstanceStatus
39
// Addresses returns a list of hostnames or ip addresses
40
// associated with the instance.
41
Addresses() ([]network.Address, error)
43
// OpenPorts opens the given port ranges on the instance, which
44
// should have been started with the given machine id.
45
OpenPorts(machineId string, ports []network.PortRange) error
47
// ClosePorts closes the given port ranges on the instance, which
48
// should have been started with the given machine id.
49
ClosePorts(machineId string, ports []network.PortRange) error
51
// Ports returns the set of port ranges open on the instance,
52
// which should have been started with the given machine id. The
53
// port ranges are returned as sorted by network.SortPortRanges().
54
Ports(machineId string) ([]network.PortRange, error)
57
// HardwareCharacteristics represents the characteristics of the instance (if known).
58
// Attributes that are nil are unknown or not supported.
59
type HardwareCharacteristics struct {
60
Arch *string `json:"arch,omitempty" yaml:"arch,omitempty"`
61
Mem *uint64 `json:"mem,omitempty" yaml:"mem,omitempty"`
62
RootDisk *uint64 `json:"root-disk,omitempty" yaml:"rootdisk,omitempty"`
63
CpuCores *uint64 `json:"cpu-cores,omitempty" yaml:"cpucores,omitempty"`
64
CpuPower *uint64 `json:"cpu-power,omitempty" yaml:"cpupower,omitempty"`
65
Tags *[]string `json:"tags,omitempty" yaml:"tags,omitempty"`
67
AvailabilityZone *string `json:"availability-zone,omitempty" yaml:"availabilityzone,omitempty"`
70
func (hc HardwareCharacteristics) String() string {
73
strs = append(strs, fmt.Sprintf("arch=%s", *hc.Arch))
75
if hc.CpuCores != nil {
76
strs = append(strs, fmt.Sprintf("cpu-cores=%d", *hc.CpuCores))
78
if hc.CpuPower != nil {
79
strs = append(strs, fmt.Sprintf("cpu-power=%d", *hc.CpuPower))
82
strs = append(strs, fmt.Sprintf("mem=%dM", *hc.Mem))
84
if hc.RootDisk != nil {
85
strs = append(strs, fmt.Sprintf("root-disk=%dM", *hc.RootDisk))
87
if hc.Tags != nil && len(*hc.Tags) > 0 {
88
strs = append(strs, fmt.Sprintf("tags=%s", strings.Join(*hc.Tags, ",")))
90
if hc.AvailabilityZone != nil && *hc.AvailabilityZone != "" {
91
strs = append(strs, fmt.Sprintf("availability-zone=%s", *hc.AvailabilityZone))
93
return strings.Join(strs, " ")
96
// Implement gnuflag.Value
97
func (hc *HardwareCharacteristics) Set(s string) error {
98
parsed, err := ParseHardware(s)
106
// MustParseHardware constructs a HardwareCharacteristics from the supplied arguments,
107
// as Parse, but panics on failure.
108
func MustParseHardware(args ...string) HardwareCharacteristics {
109
hc, err := ParseHardware(args...)
116
// ParseHardware constructs a HardwareCharacteristics from the supplied arguments,
117
// each of which must contain only spaces and name=value pairs. If any
118
// name is specified more than once, an error is returned.
119
func ParseHardware(args ...string) (HardwareCharacteristics, error) {
120
hc := HardwareCharacteristics{}
121
for _, arg := range args {
122
raws := strings.Split(strings.TrimSpace(arg), " ")
123
for _, raw := range raws {
127
if err := hc.setRaw(raw); err != nil {
128
return HardwareCharacteristics{}, err
135
// setRaw interprets a name=value string and sets the supplied value.
136
func (hc *HardwareCharacteristics) setRaw(raw string) error {
137
eq := strings.Index(raw, "=")
139
return fmt.Errorf("malformed characteristic %q", raw)
141
name, str := raw[:eq], raw[eq+1:]
145
err = hc.setArch(str)
147
err = hc.setCpuCores(str)
149
err = hc.setCpuPower(str)
153
err = hc.setRootDisk(str)
155
err = hc.setTags(str)
156
case "availability-zone":
157
err = hc.setAvailabilityZone(str)
159
return fmt.Errorf("unknown characteristic %q", name)
162
return fmt.Errorf("bad %q characteristic: %v", name, err)
167
func (hc *HardwareCharacteristics) setArch(str string) error {
169
return fmt.Errorf("already set")
171
if str != "" && !arch.IsSupportedArch(str) {
172
return fmt.Errorf("%q not recognized", str)
178
func (hc *HardwareCharacteristics) setCpuCores(str string) (err error) {
179
if hc.CpuCores != nil {
180
return fmt.Errorf("already set")
182
hc.CpuCores, err = parseUint64(str)
186
func (hc *HardwareCharacteristics) setCpuPower(str string) (err error) {
187
if hc.CpuPower != nil {
188
return fmt.Errorf("already set")
190
hc.CpuPower, err = parseUint64(str)
194
func (hc *HardwareCharacteristics) setMem(str string) (err error) {
196
return fmt.Errorf("already set")
198
hc.Mem, err = parseSize(str)
202
func (hc *HardwareCharacteristics) setRootDisk(str string) (err error) {
203
if hc.RootDisk != nil {
204
return fmt.Errorf("already set")
206
hc.RootDisk, err = parseSize(str)
210
func (hc *HardwareCharacteristics) setTags(str string) (err error) {
212
return fmt.Errorf("already set")
214
hc.Tags = parseTags(str)
218
func (hc *HardwareCharacteristics) setAvailabilityZone(str string) error {
219
if hc.AvailabilityZone != nil {
220
return fmt.Errorf("already set")
223
hc.AvailabilityZone = &str
228
// parseTags returns the tags in the value s
229
func parseTags(s string) *[]string {
233
tags := strings.Split(s, ",")
237
func parseUint64(str string) (*uint64, error) {
240
if val, err := strconv.ParseUint(str, 10, 64); err != nil {
241
return nil, fmt.Errorf("must be a non-negative integer")
249
func parseSize(str string) (*uint64, error) {
253
if m, ok := mbSuffixes[str[len(str)-1:]]; ok {
254
str = str[:len(str)-1]
257
val, err := strconv.ParseFloat(str, 64)
258
if err != nil || val < 0 {
259
return nil, fmt.Errorf("must be a non-negative float with optional M/G/T/P suffix")
262
value = uint64(math.Ceil(val))
267
var mbSuffixes = map[string]float64{
271
"P": 1024 * 1024 * 1024,