forked from solo-io/unik
/
run_instance.go
143 lines (124 loc) · 3.89 KB
/
run_instance.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package gcloud
import (
"encoding/json"
"fmt"
"github.com/Sirupsen/logrus"
"github.com/emc-advanced-dev/pkg/errors"
"github.com/emc-advanced-dev/unik/pkg/providers/common"
"github.com/emc-advanced-dev/unik/pkg/types"
"google.golang.org/api/compute/v1"
"time"
)
func (p *GcloudProvider) RunInstance(params types.RunInstanceParams) (_ *types.Instance, err error) {
logrus.WithFields(logrus.Fields{
"image-id": params.ImageId,
"mounts": params.MntPointsToVolumeIds,
"env": params.Env,
}).Infof("running instance %s", params.Name)
var instanceId string
defer func() {
if err != nil {
logrus.WithError(err).Errorf("gcloud running instance encountered an error")
if instanceId != "" {
if params.NoCleanup {
logrus.Warnf("because --no-cleanup flag was provided, not cleaning up failed instance %s0", instanceId)
return
}
logrus.Warnf("cleaning up instance %s", instanceId)
p.compute().Instances.Delete(p.config.ProjectID, p.config.Zone, instanceId)
if cleanupErr := p.state.ModifyInstances(func(instances map[string]*types.Instance) error {
delete(instances, instanceId)
return nil
}); cleanupErr != nil {
logrus.Error(errors.New("modifying instance map in state", cleanupErr))
}
}
}
}()
image, err := p.GetImage(params.ImageId)
if err != nil {
return nil, errors.New("getting image", err)
}
if err := common.VerifyMntsInput(p, image, params.MntPointsToVolumeIds); err != nil {
return nil, errors.New("invalid mapping for volume", err)
}
envData, err := json.Marshal(params.Env)
if err != nil {
return nil, errors.New("could not convert instance env to json", err)
}
//if not set, use default
if params.InstanceMemory <= 0 {
params.InstanceMemory = image.RunSpec.DefaultInstanceMemory
}
if len(envData) > 32768 {
return nil, errors.New("total length of env metadata must be <= 32768 bytes; have json string "+string(envData), nil)
}
disks := []*compute.AttachedDisk{
//boot disk
&compute.AttachedDisk{
AutoDelete: true,
Boot: true,
//DeviceName: "sd0"
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "global/images/" + image.Name,
},
},
}
for _, volumeId := range params.MntPointsToVolumeIds {
disks = append(disks, &compute.AttachedDisk{
AutoDelete: false,
Boot: false,
Source: volumeId,
})
}
instanceSpec := &compute.Instance{
Name: params.Name,
Metadata: &compute.Metadata{
Items: []*compute.MetadataItems{
&compute.MetadataItems{
Key: "ENV_DATA",
Value: pointerTo(string(envData)),
},
},
},
Disks: disks,
MachineType: fmt.Sprintf("zones/%s/machineTypes/%s", p.config.Zone, "g1-small"),
NetworkInterfaces: []*compute.NetworkInterface{
&compute.NetworkInterface{
AccessConfigs: []*compute.AccessConfig{
&compute.AccessConfig{
Type: "ONE_TO_ONE_NAT",
Name: "External NAT",
},
},
Network: "global/networks/default",
},
},
}
gInstance, err := p.compute().Instances.Insert(p.config.ProjectID, p.config.Zone, instanceSpec).Do()
if err != nil {
return nil, errors.New("creating instance on gcloud failed", err)
}
logrus.Infof("gcloud instance created: %+v", gInstance)
instanceId = params.Name
//must add instance to state before attaching volumes
instance := &types.Instance{
Id: instanceId,
Name: params.Name,
State: types.InstanceState_Pending,
Infrastructure: types.Infrastructure_GCLOUD,
ImageId: image.Id,
Created: time.Now(),
}
if err := p.state.ModifyInstances(func(instances map[string]*types.Instance) error {
instances[instance.Id] = instance
return nil
}); err != nil {
return nil, errors.New("modifying instance map in state", err)
}
logrus.WithFields(logrus.Fields{"instance": instance}).Infof("instance created succesfully")
return instance, nil
}
func pointerTo(v string) *string {
return &v
}