-
Notifications
You must be signed in to change notification settings - Fork 0
/
instances.go
108 lines (86 loc) · 2.71 KB
/
instances.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package main
import (
"context"
"encoding/binary"
"encoding/json"
"fmt"
"os"
"path/filepath"
"sync"
"time"
l "github.com/cinsk/triton-pssh/log"
"github.com/joyent/triton-go/compute"
)
const MAX_LIMIT = 1000 // max instances that can be queried at a time
func instances_pathname(input *compute.ListInstancesInput) string {
return filepath.Join(TsshRoot, "cache", TritonProfileName, "instances", fmt.Sprintf("%04d-%06d", input.Limit, input.Offset))
}
func loadInstancesFromFile(input *compute.ListInstancesInput, expiration time.Duration) ([]*compute.Instance, error) {
file := instances_pathname(input)
if Config.NoCache {
return nil, fmt.Errorf("Config.NoCache is true")
}
var instances []*compute.Instance
if err := ReadJsonFromFileCache(file, expiration, &instances); err != nil {
return instances, err
}
// TODO: need to check INFO whether it's genuine; IOW, remove it if it is empty (zero).
// at least it should have id, and one or more networks.
return instances, nil
}
func saveInstancesToFile(input *compute.ListInstancesInput, instances []*compute.Instance) error {
file := instances_pathname(input)
os.MkdirAll(filepath.Dir(file), 0755)
f, err := os.Create(file)
if err != nil {
fmt.Printf("cannot open file(%s): %s\n", file, err)
return fmt.Errorf("cannot open file(%s): %s", file, err)
}
defer f.Close()
b, _ := json.Marshal(instances)
err = binary.Write(f, binary.LittleEndian, b)
if err != nil {
fmt.Printf("cannot write NetworkInfo(%s) to the file cache: %s\n", file, err)
return fmt.Errorf("cannot write NetworkInfo(%s) to the file cache: %s", file, err)
}
return nil
}
func ListInstances(client *compute.ComputeClient, context context.Context, expiration time.Duration) chan *compute.Instance {
var limit uint16 = MAX_LIMIT
var offset uint16 = 0
ch := make(chan *compute.Instance, 1)
go func() {
defer close(ch)
var wg sync.WaitGroup
for {
l.Debug("ListMachine: offset: %v, limit: %v", offset, limit)
input := &compute.ListInstancesInput{Offset: offset, Limit: limit}
instances, err := loadInstancesFromFile(input, expiration)
if err != nil {
if instances, err = client.Instances().List(context, input); err != nil {
l.ErrQuit(1, "ListMachine API failed: %v", err)
}
err = saveInstancesToFile(input, instances)
} else {
l.Debug("using cached instances offset: %v, limit: %v", offset, limit)
}
for _, inst := range instances {
ImgCache.Prepare(inst.Image)
for _, netid := range inst.Networks {
NetCache.Prepare(netid)
}
wg.Add(1)
go func(i *compute.Instance) {
defer wg.Done()
ch <- i
}(inst)
}
if len(instances) < int(limit) {
break
}
offset += limit
}
wg.Wait()
}()
return ch
}