Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit 2729200

Browse files
authored
Merge pull request #4403 from exoscale/exoscale/template-size
exoscale/template size
2 parents 1b5de46 + 9470b46 commit 2729200

28 files changed

+790
-166
lines changed

‎Gopkg.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Gopkg.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343

4444
[[constraint]]
4545
name = "github.com/exoscale/egoscale"
46-
version = "0.9.6"
46+
version = "0.9.10"
4747

4848
[[constraint]]
4949
branch = "master"

‎drivers/exoscale/exoscale.go

Lines changed: 125 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
package exoscale
22

33
import (
4+
"bytes"
45
"encoding/base64"
56
"errors"
67
"fmt"
78
"io/ioutil"
89
"net"
910
"os"
10-
"regexp"
11+
"os/user"
12+
"path/filepath"
1113
"strings"
1214

1315
"github.com/docker/machine/libmachine/drivers"
1416
"github.com/docker/machine/libmachine/log"
1517
"github.com/docker/machine/libmachine/mcnflag"
18+
"github.com/docker/machine/libmachine/mcnutils"
1619
"github.com/docker/machine/libmachine/state"
1720
"github.com/exoscale/egoscale"
1821
)
@@ -26,9 +29,10 @@ type Driver struct {
2629
InstanceProfile string
2730
DiskSize int64
2831
Image string
29-
SecurityGroup string
30-
AffinityGroup string
32+
SecurityGroups []string
33+
AffinityGroups []string
3134
AvailabilityZone string
35+
SSHKey string
3236
KeyPair string
3337
PublicKey string
3438
UserDataFile string
@@ -43,6 +47,7 @@ const (
4347
defaultImage = "Linux Ubuntu 16.04 LTS 64-bit"
4448
defaultAvailabilityZone = "CH-DK-2"
4549
defaultSSHUser = "root"
50+
defaultSecurityGroup = "docker-machine"
4651
defaultAffinityGroupType = "host anti-affinity"
4752
defaultCloudInit = `#cloud-config
4853
manage_etc_hosts: localhost
@@ -89,7 +94,7 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
8994
mcnflag.StringSliceFlag{
9095
EnvVar: "EXOSCALE_SECURITY_GROUP",
9196
Name: "exoscale-security-group",
92-
Value: []string{},
97+
Value: []string{defaultSecurityGroup},
9398
Usage: "exoscale security group",
9499
},
95100
mcnflag.StringFlag{
@@ -104,6 +109,12 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag {
104109
Value: "",
105110
Usage: "name of the ssh user",
106111
},
112+
mcnflag.StringFlag{
113+
EnvVar: "EXOSCALE_SSH_KEY",
114+
Name: "exoscale-ssh-key",
115+
Value: "",
116+
Usage: "path to the SSH user private key",
117+
},
107118
mcnflag.StringFlag{
108119
EnvVar: "EXOSCALE_USERDATA",
109120
Name: "exoscale-userdata",
@@ -145,19 +156,23 @@ func (d *Driver) GetSSHHostname() (string, error) {
145156
func (d *Driver) GetSSHUsername() string {
146157
if d.SSHUser == "" {
147158
name := strings.ToLower(d.Image)
148-
re := regexp.MustCompile(`\b[0-9.]+\b`)
149-
version := re.FindString(d.Image)
150159

151160
if strings.Contains(name, "ubuntu") {
152161
return "ubuntu"
153162
}
154-
if strings.Contains(name, "centos") && version >= "7.3" {
163+
if strings.Contains(name, "centos") {
155164
return "centos"
156165
}
166+
if strings.Contains(name, "redhat") {
167+
return "cloud-user"
168+
}
169+
if strings.Contains(name, "fedora") {
170+
return "fedora"
171+
}
157172
if strings.Contains(name, "coreos") {
158173
return "core"
159174
}
160-
if strings.Contains(name, "debian") && version >= "8" {
175+
if strings.Contains(name, "debian") {
161176
return "debian"
162177
}
163178
return defaultSSHUser
@@ -180,17 +195,11 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
180195
d.InstanceProfile = flags.String("exoscale-instance-profile")
181196
d.DiskSize = int64(flags.Int("exoscale-disk-size"))
182197
d.Image = flags.String("exoscale-image")
183-
securityGroups := flags.StringSlice("exoscale-security-group")
184-
if len(securityGroups) == 0 {
185-
securityGroups = []string{"docker-machine"}
186-
}
187-
d.SecurityGroup = strings.Join(securityGroups, ",")
188-
affinityGroups := flags.StringSlice("exoscale-affinity-group")
189-
if len(affinityGroups) > 0 {
190-
d.AffinityGroup = strings.Join(affinityGroups, ",")
191-
}
198+
d.SecurityGroups = flags.StringSlice("exoscale-security-group")
199+
d.AffinityGroups = flags.StringSlice("exoscale-affinity-group")
192200
d.AvailabilityZone = flags.String("exoscale-availability-zone")
193201
d.SSHUser = flags.String("exoscale-ssh-user")
202+
d.SSHKey = flags.String("exoscale-ssh-key")
194203
d.UserDataFile = flags.String("exoscale-userdata")
195204
d.SetSwarmConfigFromFlags(flags)
196205

@@ -394,7 +403,6 @@ func (d *Driver) Create() error {
394403
if err != nil {
395404
return err
396405
}
397-
userData := base64.StdEncoding.EncodeToString(cloudInit)
398406

399407
log.Infof("Querying exoscale for the requested parameters...")
400408
client := egoscale.NewClient(d.URL, d.APIKey, d.APISecretKey)
@@ -414,8 +422,16 @@ func (d *Driver) Create() error {
414422
// Image UUID
415423
var tpl string
416424
images, ok := topology.Images[strings.ToLower(d.Image)]
425+
417426
if ok {
418-
tpl, ok = images[d.DiskSize]
427+
smallestDiskSize := d.DiskSize
428+
for s := range images {
429+
if s < smallestDiskSize {
430+
smallestDiskSize = s
431+
}
432+
}
433+
434+
tpl, ok = images[smallestDiskSize]
419435
}
420436
if !ok {
421437
return fmt.Errorf("Unable to find image %v with size %d",
@@ -432,9 +448,12 @@ func (d *Driver) Create() error {
432448
log.Debugf("Profile %v = %s", d.InstanceProfile, profile)
433449

434450
// Security groups
435-
securityGroups := strings.Split(d.SecurityGroup, ",")
436-
sgs := make([]string, len(securityGroups))
437-
for idx, group := range securityGroups {
451+
sgs := make([]string, 0, len(d.SecurityGroups))
452+
for _, group := range d.SecurityGroups {
453+
if group == "" {
454+
continue
455+
}
456+
438457
sg, ok := topology.SecurityGroups[group]
439458
if !ok {
440459
log.Infof("Security group %v does not exist, create it", group)
@@ -445,13 +464,15 @@ func (d *Driver) Create() error {
445464
sg = securityGroup.ID
446465
}
447466
log.Debugf("Security group %v = %s", group, sg)
448-
sgs[idx] = sg
467+
sgs = append(sgs, sg)
449468
}
450469

451470
// Affinity Groups
452-
affinityGroups := strings.Split(d.AffinityGroup, ",")
453-
ags := make([]string, len(affinityGroups))
454-
for idx, group := range affinityGroups {
471+
ags := make([]string, 0, len(d.AffinityGroups))
472+
for _, group := range d.AffinityGroups {
473+
if group == "" {
474+
continue
475+
}
455476
ag, ok := topology.AffinityGroups[group]
456477
if !ok {
457478
log.Infof("Affinity Group %v does not exist, create it", group)
@@ -462,32 +483,73 @@ func (d *Driver) Create() error {
462483
ag = affinityGroup.ID
463484
}
464485
log.Debugf("Affinity group %v = %s", group, ag)
465-
ags[idx] = ag
486+
ags = append(ags, ag)
466487
}
467488

468-
log.Infof("Generate an SSH keypair...")
469-
keypairName := fmt.Sprintf("docker-machine-%s", d.MachineName)
470-
kpresp, err := client.CreateKeypair(keypairName)
471-
if err != nil {
472-
return err
473-
}
474-
err = ioutil.WriteFile(d.GetSSHKeyPath(), []byte(kpresp.PrivateKey), 0600)
475-
if err != nil {
476-
return err
489+
// SSH key pair
490+
if d.SSHKey == "" {
491+
var keyPairName string
492+
keyPairName = fmt.Sprintf("docker-machine-%s", d.MachineName)
493+
log.Infof("Generate an SSH keypair...")
494+
resp, err := client.Request(&egoscale.CreateSSHKeyPair{
495+
Name: keyPairName,
496+
})
497+
if err != nil {
498+
return fmt.Errorf("SSH Key pair creation failed %s", err)
499+
}
500+
keyPair := resp.(*egoscale.CreateSSHKeyPairResponse).KeyPair
501+
if err = ioutil.WriteFile(d.GetSSHKeyPath(), []byte(keyPair.PrivateKey), 0600); err != nil {
502+
return fmt.Errorf("SSH public key could not be written %s", err)
503+
}
504+
d.KeyPair = keyPairName
505+
} else {
506+
log.Infof("Importing SSH key from %s", d.SSHKey)
507+
508+
sshKey := d.SSHKey
509+
if strings.HasPrefix(sshKey, "~/") {
510+
usr, _ := user.Current()
511+
sshKey = filepath.Join(usr.HomeDir, sshKey[2:])
512+
} else {
513+
var err error
514+
if sshKey, err = filepath.Abs(sshKey); err != nil {
515+
return err
516+
}
517+
}
518+
519+
// Sending the SSH public key through the cloud-init config
520+
pubKey, err := ioutil.ReadFile(sshKey + ".pub")
521+
if err != nil {
522+
return fmt.Errorf("Cannot read SSH public key %s", err)
523+
}
524+
525+
sshAuthorizedKeys := `
526+
ssh_authorized_keys:
527+
- `
528+
cloudInit = bytes.Join([][]byte{cloudInit, []byte(sshAuthorizedKeys), pubKey}, []byte(""))
529+
530+
// Copying the private key into docker-machine
531+
if err := mcnutils.CopyFile(sshKey, d.GetSSHKeyPath()); err != nil {
532+
return fmt.Errorf("Unable to copy SSH file: %s", err)
533+
}
534+
if err := os.Chmod(d.GetSSHKeyPath(), 0600); err != nil {
535+
return fmt.Errorf("Unable to set permissions on the SSH file: %s", err)
536+
}
477537
}
478-
d.KeyPair = keypairName
479538

480539
log.Infof("Spawn exoscale host...")
481540
log.Debugf("Using the following cloud-init file:")
482541
log.Debugf("%s", string(cloudInit))
483542

543+
// Base64 encode the userdata
544+
userData := base64.StdEncoding.EncodeToString(cloudInit)
545+
484546
req := &egoscale.DeployVirtualMachine{
485547
TemplateID: tpl,
486548
ServiceOfferingID: profile,
487549
UserData: userData,
488550
ZoneID: zone,
489-
KeyPair: d.KeyPair,
490551
Name: d.MachineName,
552+
KeyPair: d.KeyPair,
491553
DisplayName: d.MachineName,
492554
RootDiskSize: d.DiskSize,
493555
SecurityGroupIDs: sgs,
@@ -506,6 +568,19 @@ func (d *Driver) Create() error {
506568
d.IPAddress = IPAddress.String()
507569
}
508570
d.ID = vm.ID
571+
log.Infof("IP Address: %v, SSH User: %v", d.IPAddress, d.GetSSHUsername())
572+
573+
// Destroy the SSH key from CloudStack
574+
if d.KeyPair != "" {
575+
if err := drivers.WaitForSSH(d); err != nil {
576+
return err
577+
}
578+
579+
if err := client.BooleanRequest(&egoscale.DeleteSSHKeyPair{Name: d.KeyPair}); err != nil {
580+
return err
581+
}
582+
d.KeyPair = ""
583+
}
509584

510585
return nil
511586
}
@@ -547,19 +622,25 @@ func (d *Driver) Kill() error {
547622

548623
// Remove destroys the VM instance and the associated SSH key.
549624
func (d *Driver) Remove() error {
550-
cs := d.client()
625+
client := d.client()
551626

552-
// Destroy the SSH key
553-
if err := cs.BooleanRequest(&egoscale.DeleteSSHKeyPair{Name: d.KeyPair}); err != nil {
554-
return err
627+
// Destroy the SSH key from CloudStack
628+
if d.KeyPair != "" {
629+
if err := client.BooleanRequest(&egoscale.DeleteSSHKeyPair{Name: d.KeyPair}); err != nil {
630+
return err
631+
}
555632
}
556633

557634
// Destroy the virtual machine
558-
_, err := cs.AsyncRequest(&egoscale.DestroyVirtualMachine{ID: d.ID}, d.async)
635+
if d.ID != "" {
636+
if _, err := client.AsyncRequest(&egoscale.DestroyVirtualMachine{ID: d.ID}, d.async); err != nil {
637+
return err
638+
}
639+
}
559640

560641
log.Infof("The Anti-Affinity group and Security group were not removed")
561642

562-
return err
643+
return nil
563644
}
564645

565646
// Build a cloud-init user data string that will install and run

‎vendor/github.com/exoscale/egoscale/.travis.yml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎vendor/github.com/exoscale/egoscale/AUTHORS

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)