"fmt"
"log"
"strings"
+ "sync"
"git.curoverse.com/arvados.git/lib/cloud"
"git.curoverse.com/arvados.git/sdk/go/arvados"
SecurityGroupIDs []string
SubnetID string
AdminUsername string
- KeyPairName string
}
type ec2Interface interface {
dispatcherID cloud.InstanceSetID
logger logrus.FieldLogger
client ec2Interface
- importedKey bool
+ keysMtx sync.Mutex
+ keys map[string]string
}
func newEC2InstanceSet(config json.RawMessage, dispatcherID cloud.InstanceSetID, logger logrus.FieldLogger) (prv cloud.InstanceSet, err error) {
"")).
WithRegion(instanceSet.ec2config.Region)
instanceSet.client = ec2.New(session.Must(session.NewSession(awsConfig)))
+ instanceSet.keys = make(map[string]string)
return instanceSet, nil
}
initCommand cloud.InitCommand,
publicKey ssh.PublicKey) (cloud.Instance, error) {
- if !instanceSet.importedKey {
+ keyFingerprint := ssh.FingerprintSHA256(publicKey)
+ instanceSet.keysMtx.Lock()
+ var keyname string
+ var ok bool
+ if keyname, ok = instanceSet.keys[keyFingerprint]; !ok {
+ keyname = "arvados-dispatch-keypair-" + keyFingerprint
instanceSet.client.ImportKeyPair(&ec2.ImportKeyPairInput{
- KeyName: &instanceSet.ec2config.KeyPairName,
+ KeyName: &keyname,
PublicKeyMaterial: ssh.MarshalAuthorizedKey(publicKey),
})
- instanceSet.importedKey = true
+ instanceSet.keys[keyFingerprint] = keyname
}
+ instanceSet.keysMtx.Unlock()
ec2tags := []*ec2.Tag{
&ec2.Tag{
InstanceType: &instanceType.ProviderType,
MaxCount: aws.Int64(1),
MinCount: aws.Int64(1),
- KeyName: &instanceSet.ec2config.KeyPairName,
+ KeyName: &keyname,
NetworkInterfaces: []*ec2.InstanceNetworkInterfaceSpecification{
&ec2.InstanceNetworkInterfaceSpecification{
}},
}
- if instanceType.AttachScratch {
+ if instanceType.AddedScratch > 0 {
rii.BlockDeviceMappings = []*ec2.BlockDeviceMapping{&ec2.BlockDeviceMapping{
DeviceName: aws.String("/dev/xvdt"),
Ebs: &ec2.EbsBlockDevice{
DeleteOnTermination: aws.Bool(true),
- VolumeSize: aws.Int64((int64(instanceType.Scratch) / 1000000000) + 1),
+ VolumeSize: aws.Int64((int64(instanceType.AddedScratch) / 1000000000) + 1),
VolumeType: aws.String("gp2"),
}}}
}
// AccessKeyID: XXXXXXXXXXXXXX
// SecretAccessKey: xxxxxxxxxxxxxxxxxxxx
// Region: us-east-1
-// SecurityGroupId: sg-xxxxxxxx
-// SubnetId: subnet-xxxxxxxx
+// SecurityGroupIDs: [sg-xxxxxxxx]
+// SubnetID: subnet-xxxxxxxx
// AdminUsername: crunch
-// KeyPairName: arvados-dispatcher-keypair
package ec2
Preemptible: false,
},
"tiny-with-extra-scratch": arvados.InstanceType{
- Name: "tiny",
- ProviderType: "t2.micro",
- VCPUs: 1,
- RAM: 4000000000,
- Scratch: 20000000000,
- Price: .02,
- Preemptible: false,
- AttachScratch: true,
+ Name: "tiny",
+ ProviderType: "t2.micro",
+ VCPUs: 1,
+ RAM: 4000000000,
+ Price: .02,
+ Preemptible: false,
+ AddedScratch: 20000000000,
},
"tiny-preemptible": arvados.InstanceType{
Name: "tiny",
dispatcherID: "test123",
logger: logrus.StandardLogger(),
client: &ec2stub{},
+ keys: make(map[string]string),
}
return &ap, cloud.ImageID("blob"), cluster, nil
}
}
type InstanceType struct {
- Name string
- ProviderType string
- VCPUs int
- RAM ByteSize
- Scratch ByteSize
- Price float64
- Preemptible bool
- AttachScratch bool
+ Name string
+ ProviderType string
+ VCPUs int
+ RAM ByteSize
+ Scratch ByteSize
+ IncludedScratch ByteSize
+ AddedScratch ByteSize
+ Price float64
+ Preemptible bool
}
type Dispatch struct {
if t.ProviderType == "" {
t.ProviderType = t.Name
}
+ if t.Scratch == 0 {
+ t.Scratch = t.IncludedScratch + t.AddedScratch
+ }
+ if (t.Scratch - t.IncludedScratch) > t.AddedScratch {
+ t.AddedScratch = t.Scratch - t.IncludedScratch
+ }
+ if t.Scratch != (t.IncludedScratch + t.AddedScratch) {
+ return fmt.Errorf("%v: Scratch != (IncludedScratch + AddedScratch)", t.Name)
+ }
(*it)[t.Name] = t
}
return nil