Created
August 23, 2017 10:21
-
-
Save kirmorozov/a5989adcea4641694a3fb6c064a3e1e8 to your computer and use it in GitHub Desktop.
Patches for docker Machine to Support VCloud Direct 5.6
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: api.go | |
IDEA additional info: | |
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP | |
<+>US-ASCII | |
=================================================================== | |
--- api.go (revision 0d7be903f950c035d6e95eabfd9b011a507f4488) | |
+++ api.go (revision 17fa3ab2a352908cb4104a11f7c5c0e5eb8e10bb) | |
@@ -23,6 +23,7 @@ | |
type Client struct { | |
VAToken string // vCloud Air authorization token | |
VAEndpoint url.URL // vCloud Air API endpoint | |
+ VAVersion string | |
Region string // Region where the compute resource lives. | |
VCDToken string // Access Token (authorization header) | |
VCDAuthHeader string // Authorization header | |
@@ -87,7 +88,7 @@ | |
req.SetBasicAuth(user, pass) | |
// Add the Accept header for vCA | |
- req.Header.Add("Accept", "application/xml;version=5.6") | |
+ req.Header.Add("Accept", c.VAVersion) | |
resp, err := checkResp(c.Http.Do(req)) | |
if err != nil { | |
@@ -123,7 +124,7 @@ | |
req := c.NewRequest(map[string]string{}, "GET", s, nil) | |
// Add the Accept header for vCA | |
- req.Header.Add("Accept", "application/xml;version=5.6") | |
+ req.Header.Add("Accept", c.VAVersion) | |
// Set Authorization Header for vCA | |
req.Header.Add("x-vchs-authorization", c.VAToken) | |
@@ -159,7 +160,7 @@ | |
req := c.NewRequest(map[string]string{}, "GET", s, nil) | |
// Add the Accept header for vCA | |
- req.Header.Add("Accept", "application/xml;version=5.6") | |
+ req.Header.Add("Accept", c.VAVersion) | |
// Set Authorization Header | |
req.Header.Add("x-vchs-authorization", c.VAToken) | |
@@ -199,7 +200,7 @@ | |
req := c.NewRequest(map[string]string{}, "POST", s, nil) | |
// Add the Accept header for vCA | |
- req.Header.Add("Accept", "application/xml;version=5.6") | |
+ req.Header.Add("Accept", c.VAVersion) | |
// Set Authorization Header | |
req.Header.Add("x-vchs-authorization", c.VAToken) | |
@@ -285,6 +286,8 @@ | |
// Authenticate is an helper function that performs a complete login in vCloud | |
// Air and in the backend vCloud Director instance. | |
func (c *Client) Authenticate(username, password, computeid, vdcid string) (Vdc, error) { | |
+ | |
+ c.VAVersion = "application/xml;version=5.6" | |
// Authorize | |
vaservicehref, err := c.vaauthorize(username, password) | |
if err != nil { | |
@@ -340,7 +343,7 @@ | |
// Add the authorization header | |
req.Header.Add(c.VCDAuthHeader, c.VCDToken) | |
// Add the Accept header for VCD | |
- req.Header.Add("Accept", "application/*+xml;version=5.6") | |
+ req.Header.Add("Accept", c.VAVersion) | |
} | |
return req | |
@@ -359,7 +362,7 @@ | |
req := c.NewRequest(map[string]string{}, "DELETE", s, nil) | |
// Add the Accept header for vCA | |
- req.Header.Add("Accept", "application/xml;version=5.6") | |
+ req.Header.Add("Accept", c.VAVersion) | |
// Set Authorization Header | |
req.Header.Add("x-vchs-authorization", c.VAToken) | |
Index: api_vcloud.go | |
IDEA additional info: | |
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP | |
<+>US-ASCII | |
=================================================================== | |
--- api_vcloud.go (revision dc639ec9bb1f00fa00de79b83877c88c7253ef03) | |
+++ api_vcloud.go (revision dc639ec9bb1f00fa00de79b83877c88c7253ef03) | |
@@ -0,0 +1,216 @@ | |
+/* | |
+ * Copyright 2014 VMware, Inc. All rights reserved. Licensed under the Apache v2 License. | |
+ */ | |
+ | |
+// Package govcloudair provides a simple binding for vCloud Air REST APIs. | |
+package govcloudair | |
+ | |
+import ( | |
+ "fmt" | |
+ "net/url" | |
+ "os" | |
+) | |
+ | |
+ | |
+type supportedVersions struct { | |
+ VersionInfo struct { | |
+ Version string `xml:"Version"` | |
+ LoginUrl string `xml:"LoginUrl"` | |
+ } `xml:"VersionInfo"` | |
+} | |
+ | |
+type vCloudOrg struct { | |
+ Link []struct { | |
+ Rel string `xml:"rel,attr"` | |
+ Type string `xml:"type,attr"` | |
+ Name string `xml:"name,attr"` | |
+ HREF string `xml:"href,attr"` | |
+} `xml:"Link"` | |
+} | |
+ | |
+ | |
+func (c *Client) vcdloginurl() (u *url.URL, err error) { | |
+ | |
+ s := c.VCDVDCHREF | |
+ s.Path += "/versions" | |
+ | |
+ // No point in checking for errors here | |
+ req := c.NewRequest(map[string]string{}, "GET", s, nil) | |
+ | |
+ resp, err := checkResp(c.Http.Do(req)) | |
+ if err != nil { | |
+ return &url.URL{}, err | |
+ } | |
+ defer resp.Body.Close() | |
+ | |
+ supportedVersions := new(supportedVersions) | |
+ | |
+ err = decodeBody(resp, supportedVersions) | |
+ | |
+ if err != nil { | |
+ return u, fmt.Errorf("error decoding versions response: %s", err) | |
+ } | |
+ | |
+ u, err = url.Parse(supportedVersions.VersionInfo.LoginUrl) | |
+ if err != nil { | |
+ return u, fmt.Errorf("couldn't find a LoginUrl in versions") | |
+ } | |
+ return u, nil | |
+} | |
+ | |
+ | |
+func (c *Client) vcauthorize(user, pass string) (u url.URL, err error) { | |
+ | |
+ if user == "" { | |
+ user = os.Getenv("VCLOUDAIR_USERNAME") | |
+ } | |
+ | |
+ if pass == "" { | |
+ pass = os.Getenv("VCLOUDAIR_PASSWORD") | |
+ } | |
+ | |
+ // LoginUrl | |
+ sessionRef, err := c.vcdloginurl() | |
+ if err != nil { | |
+ return url.URL{}, fmt.Errorf("error finding LoginUrl: %s", err) | |
+ } | |
+ | |
+ // No point in checking for errors here | |
+ req := c.NewRequest(map[string]string{}, "POST", *sessionRef, nil) | |
+ | |
+ // Set Basic Authentication Header | |
+ req.SetBasicAuth(user, pass) | |
+ | |
+ // Add the Accept header for vCA | |
+ req.Header.Add("Accept", c.VAVersion) | |
+ | |
+ resp, err := checkResp(c.Http.Do(req)) | |
+ if err != nil { | |
+ return url.URL{}, err | |
+ } | |
+ defer resp.Body.Close() | |
+ | |
+ | |
+ | |
+ // Store the authentication header | |
+ c.VCDToken = resp.Header.Get("x-vcloud-authorization") | |
+ c.VCDAuthHeader = "x-vcloud-authorization" | |
+ | |
+ session := new(session) | |
+ | |
+ if err = decodeBody(resp, session); err != nil { | |
+ return url.URL{}, fmt.Errorf("error decoding session response: %s", err) | |
+ } | |
+ | |
+ // Loop in the session struct to find right service and compute resource. | |
+ for _, s := range session.Link { | |
+ if s.Type == "application/vnd.vmware.vcloud.org+xml" && s.Rel == "down" { | |
+ u, err := url.ParseRequestURI(s.HREF) | |
+ return *u, err | |
+ } | |
+ } | |
+ return url.URL{}, fmt.Errorf("couldn't find a Service List in current session") | |
+} | |
+ | |
+ | |
+ | |
+func (c *Client) retrieveVDCHREF(orgRef url.URL) (u url.URL, err error) { | |
+ | |
+ req := c.NewRequest(map[string]string{}, "GET", orgRef, nil) | |
+ | |
+ // Add the Accept header for vCD | |
+ //req.Header.Add("Accept", "application/*+xml;version=5.5") | |
+ | |
+ // TODO: wrap into checkresp to parse error | |
+ resp, err := checkResp(c.Http.Do(req)) | |
+ if err != nil { | |
+ return url.URL{}, fmt.Errorf("error processing org: %s", err) | |
+ } | |
+ defer resp.Body.Close() | |
+ | |
+ vcloudorg := new(vCloudOrg) | |
+ | |
+ if err = decodeBody(resp, vcloudorg); err != nil { | |
+ return url.URL{}, fmt.Errorf("error decoding vCloudOrg response: %s", err) | |
+ } | |
+ | |
+ // Get the VDC ref from the Org | |
+ for _, s := range vcloudorg.Link { | |
+ if s.Type == "application/vnd.vmware.vcloud.vdc+xml" && s.Rel == "down" { | |
+ u, err := url.ParseRequestURI(s.HREF) | |
+ return *u, err | |
+ } | |
+ } | |
+ | |
+ return url.URL{}, fmt.Errorf("error finding the organization VDC") | |
+} | |
+ | |
+// Authenticate is an helper function that performs a complete login in vCloud | |
+// Air and in the backend vCloud Director instance. | |
+func (c *Client) VCloudAuthenticate(username, password, computeid, vdcid string) (Vdc, error) { | |
+ | |
+ c.VAVersion = "application/*+xml;version=5.5" | |
+ | |
+ // Authorize | |
+ vcOrgRef, err := c.vcauthorize(username, password) | |
+ if err != nil { | |
+ return Vdc{}, fmt.Errorf("error vCloud Authorizing: %s", err) | |
+ } | |
+ | |
+ vcVDCHREF, err := c.retrieveVDCHREF(vcOrgRef) | |
+ if err != nil { | |
+ return Vdc{}, fmt.Errorf("error Acquiring VDC url: %s", err) | |
+ } else { | |
+ c.VCDVDCHREF = vcVDCHREF | |
+ } | |
+ | |
+ v, err := c.retrieveVDC() | |
+ if err != nil { | |
+ return Vdc{}, fmt.Errorf("error Acquiring VDC: %s", err) | |
+ } | |
+ | |
+ return v, nil | |
+ | |
+} | |
+ | |
+ | |
+// Disconnect performs a disconnection from the vCloud Air API endpoint. | |
+func (c *Client) VCloudDisconnect() error { | |
+ if c.VCDToken == "" && c.VCDAuthHeader == "" && c.VAToken == "" { | |
+ return fmt.Errorf("cannot disconnect, client is not authenticated") | |
+ } | |
+ /* | |
+ var u *url.URL | |
+ var err error | |
+ | |
+ if os.Getenv("VCLOUD_ENDPOINT") != "" { | |
+ u, err = url.ParseRequestURI(os.Getenv("VCLOUD_ENDPOINT")) | |
+ if err != nil { | |
+ return fmt.Errorf("Disconnection: cannot parse endpoint coming from VCLOUD_ENDPOINT") | |
+ } | |
+ } else { | |
+ return fmt.Errorf("Disconnection: Please provide VCLOUD_ENDPOINT") | |
+ } | |
+ | |
+ c.VCDVDCHREF = *u | |
+ | |
+ // LoginUrl | |
+ sessionRef, err := c.vcdloginurl() | |
+ if err != nil { | |
+ return fmt.Errorf("error finding LoginUrl on disconnect: %s", err) | |
+ } | |
+ | |
+ req := c.NewRequest(map[string]string{}, "DELETE", *sessionRef, nil) | |
+ | |
+ // Add the Accept header for vCA | |
+ req.Header.Add("Accept", c.VAVersion) | |
+ | |
+ // Set Authorization Header | |
+ req.Header.Add(c.VCDAuthHeader, c.VCDToken) | |
+ | |
+ if _, err := checkResp(c.Http.Do(req)); err != nil { | |
+ return fmt.Errorf("error processing session delete for vchs: %s", err) | |
+ } | |
+ */ | |
+ return nil | |
+} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: drivers/vmwarevcloud/vcloud.go | |
IDEA additional info: | |
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP | |
<+>US-ASCII | |
=================================================================== | |
--- drivers/vmwarevcloud/vcloud.go (revision 2fbb7d7548834d152fe918ecd2b69d2be2b2623e) | |
+++ drivers/vmwarevcloud/vcloud.go (revision 2fbb7d7548834d152fe918ecd2b69d2be2b2623e) | |
@@ -0,0 +1,783 @@ | |
+/* | |
+ * Copyright 2014 VMware, Inc. All rights reserved. Licensed under the Apache v2 License. | |
+ */ | |
+ | |
+package vmwarevcloud | |
+ | |
+import ( | |
+ "fmt" | |
+ "io/ioutil" | |
+ "path/filepath" | |
+ "strings" | |
+ | |
+ "net/url" | |
+ | |
+ "github.com/vmware/govcloudair" | |
+ | |
+ "github.com/codegangsta/cli" | |
+ "github.com/docker/machine/drivers" | |
+ "github.com/docker/machine/log" | |
+ "github.com/docker/machine/provider" | |
+ "github.com/docker/machine/ssh" | |
+ "github.com/docker/machine/state" | |
+ "github.com/docker/machine/utils" | |
+) | |
+ | |
+type Driver struct { | |
+ IPAddress string | |
+ Endpoint string | |
+ UserName string | |
+ UserPassword string | |
+ ComputeID string | |
+ VDCID string | |
+ OrgVDCNet string | |
+ EdgeGateway string | |
+ PublicIP string | |
+ Catalog string | |
+ CatalogItem string | |
+ MachineName string | |
+ SSHUser string | |
+ SSHPort int | |
+ CustomScript string | |
+ DockerPort int | |
+ Provision bool | |
+ CPUCount int | |
+ MemorySize int | |
+ CaCertPath string | |
+ PrivateKeyPath string | |
+ SwarmMaster bool | |
+ SwarmHost string | |
+ SwarmDiscovery string | |
+ VAppID string | |
+ storePath string | |
+} | |
+ | |
+func init() { | |
+ drivers.Register("vmwarevcloud", &drivers.RegisteredDriver{ | |
+ New: NewDriver, | |
+ GetCreateFlags: GetCreateFlags, | |
+ }) | |
+} | |
+ | |
+// GetCreateFlags registers the flags this driver adds to | |
+// "docker hosts create" | |
+func GetCreateFlags() []cli.Flag { | |
+ return []cli.Flag{ | |
+ cli.StringFlag{ | |
+ EnvVar: "VCLOUD_ENDPOINT", | |
+ Name: "vmwarevcloud-endpoint", | |
+ Usage: "vCloud endpoint", | |
+ }, | |
+ cli.StringFlag{ | |
+ EnvVar: "VCLOUD_USERNAME", | |
+ Name: "vmwarevcloud-username", | |
+ Usage: "vCloud username", | |
+ }, | |
+ cli.StringFlag{ | |
+ EnvVar: "VCLOUD_PASSWORD", | |
+ Name: "vmwarevcloud-password", | |
+ Usage: "vCloud password", | |
+ }, | |
+ cli.StringFlag{ | |
+ EnvVar: "VCLOUD_COMPUTEID", | |
+ Name: "vmwarevcloud-computeid", | |
+ Usage: "vCloud Compute ID (if using Dedicated Cloud)", | |
+ }, | |
+ cli.StringFlag{ | |
+ EnvVar: "VCLOUD_VDCID", | |
+ Name: "vmwarevcloud-vdcid", | |
+ Usage: "vCloud VDC ID", | |
+ }, | |
+ cli.StringFlag{ | |
+ EnvVar: "VCLOUD_ORGVDCNETWORK", | |
+ Name: "vmwarevcloud-orgvdcnetwork", | |
+ Usage: "vCloud Org VDC Network (Default is <vdcid>-default-routed)", | |
+ }, | |
+ cli.StringFlag{ | |
+ EnvVar: "VCLOUD_EDGEGATEWAY", | |
+ Name: "vmwarevcloud-edgegateway", | |
+ Usage: "vCloud Org Edge Gateway (Default is <vdcid>)", | |
+ }, | |
+ cli.StringFlag{ | |
+ EnvVar: "VCLOUD_PUBLICIP", | |
+ Name: "vmwarevcloud-publicip", | |
+ Usage: "vCloud Org Public IP to use", | |
+ }, | |
+ cli.StringFlag{ | |
+ EnvVar: "VCLOUD_CATALOG", | |
+ Name: "vmwarevcloud-catalog", | |
+ Usage: "vCloud Catalog (default is Public Catalog)", | |
+ Value: "Public Catalog", | |
+ }, | |
+ cli.StringFlag{ | |
+ EnvVar: "VCLOUD_CATALOGITEM", | |
+ Name: "vmwarevcloud-catalogitem", | |
+ Usage: "vCloud Catalog Item (default is Ubuntu Precise)", | |
+ Value: "Ubuntu Server 12.04 LTS (amd64 20140927)", | |
+ }, | |
+ | |
+ // BoolTFlag is true by default. | |
+ cli.BoolTFlag{ | |
+ EnvVar: "VCLOUD_PROVISION", | |
+ Name: "vmwarevcloud-provision", | |
+ Usage: "vCloud Install Docker binaries (default is true)", | |
+ }, | |
+ | |
+ cli.IntFlag{ | |
+ EnvVar: "VCLOUD_CPU_COUNT", | |
+ Name: "vmwarevcloud-cpu-count", | |
+ Usage: "vCloud VM Cpu Count (default 1)", | |
+ Value: 1, | |
+ }, | |
+ cli.IntFlag{ | |
+ EnvVar: "VCLOUD_MEMORY_SIZE", | |
+ Name: "vmwarevcloud-memory-size", | |
+ Usage: "vCloud VM Memory Size in MB (default 2048)", | |
+ Value: 2048, | |
+ }, | |
+ cli.StringFlag{ | |
+ EnvVar: "VCLOUD_CUSTOM_SCRIPT", | |
+ Name: "vmwarevcloud-custom-script", | |
+ Usage: "vCloud Custom Script", | |
+ Value: "root", | |
+ }, | |
+ cli.StringFlag{ | |
+ EnvVar: "VCLOUD_SSH_USER", | |
+ Name: "vmwarevcloud-ssh-user", | |
+ Usage: "vCloud SSH user", | |
+ Value: "root", | |
+ }, | |
+ cli.IntFlag{ | |
+ EnvVar: "VCLOUD_SSH_PORT", | |
+ Name: "vmwarevcloud-ssh-port", | |
+ Usage: "vCloud SSH port", | |
+ Value: 22, | |
+ }, | |
+ cli.IntFlag{ | |
+ EnvVar: "VCLOUD_DOCKER_PORT", | |
+ Name: "vmwarevcloud-docker-port", | |
+ Usage: "vCloud Docker port", | |
+ Value: 2376, | |
+ }, | |
+ } | |
+} | |
+ | |
+func NewDriver(machineName string, storePath string, caCert string, privateKey string) (drivers.Driver, error) { | |
+ driver := &Driver{MachineName: machineName, storePath: storePath, CaCertPath: caCert, PrivateKeyPath: privateKey} | |
+ return driver, nil | |
+} | |
+ | |
+func (d *Driver) NewClient() (*govcloudair.Client, error) { | |
+ | |
+ var u *url.URL | |
+ var err error | |
+ | |
+ | |
+ p, err := govcloudair.NewClient() | |
+ if err != nil { | |
+ return p, err | |
+ } | |
+ | |
+ if d.Endpoint == "" { | |
+ return p, fmt.Errorf("Please provide VCLOUD_ENDPOINT") | |
+ } else { | |
+ u, err = url.ParseRequestURI(d.Endpoint) | |
+ if err != nil { | |
+ return p, fmt.Errorf("cannot parse endpoint coming from VCLOUD_ENDPOINT") | |
+ } | |
+ } | |
+ | |
+ p.VCDVDCHREF = *u | |
+ | |
+ return p, err | |
+} | |
+ | |
+func (d *Driver) AuthorizePort(ports []*drivers.Port) error { | |
+ return nil | |
+} | |
+ | |
+func (d *Driver) DeauthorizePort(ports []*drivers.Port) error { | |
+ return nil | |
+} | |
+ | |
+func (d *Driver) GetMachineName() string { | |
+ return d.MachineName | |
+} | |
+ | |
+func (d *Driver) GetSSHHostname() (string, error) { | |
+ return d.GetIP() | |
+} | |
+ | |
+func (d *Driver) GetSSHKeyPath() string { | |
+ return filepath.Join(d.storePath, "id_rsa") | |
+} | |
+ | |
+func (d *Driver) GetSSHPort() (int, error) { | |
+ if d.SSHPort == 0 { | |
+ d.SSHPort = 22 | |
+ } | |
+ | |
+ return d.SSHPort, nil | |
+} | |
+ | |
+func (d *Driver) GetSSHUsername() string { | |
+ if d.SSHUser == "" { | |
+ d.SSHUser = "root" | |
+ } | |
+ | |
+ return d.SSHUser | |
+} | |
+ | |
+func (d *Driver) GetProviderType() provider.ProviderType { | |
+ return provider.Remote | |
+} | |
+ | |
+// Driver interface implementation | |
+func (d *Driver) DriverName() string { | |
+ return "vmwarevcloud" | |
+} | |
+ | |
+func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error { | |
+ | |
+ d.Endpoint = flags.String("vmwarevcloud-endpoint") | |
+ d.UserName = flags.String("vmwarevcloud-username") | |
+ d.UserPassword = flags.String("vmwarevcloud-password") | |
+ d.VDCID = flags.String("vmwarevcloud-vdcid") | |
+ d.PublicIP = flags.String("vmwarevcloud-publicip") | |
+ d.SwarmMaster = flags.Bool("swarm-master") | |
+ d.SwarmHost = flags.String("swarm-host") | |
+ d.SwarmDiscovery = flags.String("swarm-discovery") | |
+ | |
+ // Check for required Params | |
+ if d.UserName == "" || d.UserPassword == "" || d.VDCID == "" || d.PublicIP == "" { | |
+ return fmt.Errorf("Please specify vcloudair mandatory params using options: -vmwarevcloud-username -vmwarevcloud-password -vmwarevcloud-vdcid and -vmwarevcloud-publicip") | |
+ } | |
+ | |
+ // If ComputeID is not set we're using a VPC, hence setting ComputeID = VDCID | |
+ if flags.String("vmwarevcloud-computeid") == "" { | |
+ d.ComputeID = flags.String("vmwarevcloud-vdcid") | |
+ } else { | |
+ d.ComputeID = flags.String("vmwarevcloud-computeid") | |
+ } | |
+ | |
+ // If the Org VDC Network is empty, set it to the default routed network. | |
+ if flags.String("vmwarevcloud-orgvdcnetwork") == "" { | |
+ d.OrgVDCNet = flags.String("vmwarevcloud-vdcid") + "-default-routed" | |
+ } else { | |
+ d.OrgVDCNet = flags.String("vmwarevcloud-orgvdcnetwork") | |
+ } | |
+ | |
+ // If the Edge Gateway is empty, just set it to the default edge gateway. | |
+ if flags.String("vmwarevcloud-edgegateway") == "" { | |
+ d.EdgeGateway = flags.String("vmwarevcloud-vdcid") | |
+ } else { | |
+ d.EdgeGateway = flags.String("vmwarevcloud-edgegateway") | |
+ } | |
+ | |
+ d.Catalog = flags.String("vmwarevcloud-catalog") | |
+ d.CatalogItem = flags.String("vmwarevcloud-catalogitem") | |
+ | |
+ d.DockerPort = flags.Int("vmwarevcloud-docker-port") | |
+ d.CustomScript = flags.String("vmwarevcloud-custom-script") | |
+ d.SSHUser = flags.String("vmwarevcloud-ssh-user") | |
+ d.SSHPort = flags.Int("vmwarevcloud-ssh-port") | |
+ d.Provision = flags.Bool("vmwarevcloud-provision") | |
+ d.CPUCount = flags.Int("vmwarevcloud-cpu-count") | |
+ d.MemorySize = flags.Int("vmwarevcloud-memory-size") | |
+ | |
+ return nil | |
+} | |
+ | |
+func (d *Driver) GetURL() (string, error) { | |
+ return fmt.Sprintf("tcp://%s:%d", d.PublicIP, d.DockerPort), nil | |
+} | |
+ | |
+func (d *Driver) GetIP() (string, error) { | |
+ return d.PublicIP, nil | |
+} | |
+ | |
+func (d *Driver) GetState() (state.State, error) { | |
+ | |
+ p, err := d.NewClient() | |
+ if err != nil { | |
+ return state.Error, err | |
+ } | |
+ | |
+ log.Debug("Connecting to vCloud to fetch vApp Status...") | |
+ // Authenticate to vCloud | |
+ v, err := p.VCloudAuthenticate(d.UserName, d.UserPassword, d.ComputeID, d.VDCID) | |
+ if err != nil { | |
+ return state.Error, err | |
+ } | |
+ | |
+ vapp, err := v.FindVAppByID(d.VAppID) | |
+ if err != nil { | |
+ return state.Error, err | |
+ } | |
+ | |
+ status, err := vapp.GetStatus() | |
+ if err != nil { | |
+ return state.Error, err | |
+ } | |
+ | |
+ if err = p.VCloudDisconnect(); err != nil { | |
+ return state.Error, err | |
+ } | |
+ | |
+ switch status { | |
+ case "POWERED_ON": | |
+ return state.Running, nil | |
+ case "POWERED_OFF": | |
+ return state.Stopped, nil | |
+ } | |
+ return state.None, nil | |
+ | |
+} | |
+ | |
+func (d *Driver) PreCreateCheck() error { | |
+ return nil | |
+} | |
+ | |
+func (d *Driver) Create() error { | |
+ | |
+ key, err := d.createSSHKey() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ p, err := d.NewClient() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ log.Infof("Connecting to vCloud...") | |
+ // Authenticate to vCloud | |
+ v, err := p.VCloudAuthenticate(d.UserName, d.UserPassword, d.ComputeID, d.VDCID) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ // Find VDC Network | |
+ net, err := v.FindVDCNetwork(d.OrgVDCNet) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ // Find our Edge Gateway | |
+ edge, err := v.FindEdgeGateway(d.EdgeGateway) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ // Get the Org our VDC belongs to | |
+ org, err := v.GetVDCOrg() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ // Find our Catalog | |
+ cat, err := org.FindCatalog(d.Catalog) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ // Find our Catalog Item | |
+ cati, err := cat.FindCatalogItem(d.CatalogItem) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ // Fetch the vApp Template in the Catalog Item | |
+ vapptemplate, err := cati.GetVAppTemplate() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ // Create a new empty vApp | |
+ vapp := govcloudair.NewVApp(p) | |
+ | |
+ log.Infof("Creating a new vApp: %s...", d.MachineName) | |
+ // Compose the vApp with ComposeVApp | |
+ task, err := vapp.ComposeVApp(net, vapptemplate, d.MachineName, "Container Host created with Docker Host") | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ // Wait for the creation to be completed | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ task, err = vapp.ChangeCPUcount(d.CPUCount) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ task, err = vapp.ChangeMemorySize(d.MemorySize) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ sshCustomScript := "mkdir -p /root/.ssh ; echo \"" + strings.TrimSpace(key) + "\" > /root/.ssh/authorized_keys" | |
+ | |
+ if d.CustomScript != "" { | |
+ userCustomScript, err := ioutil.ReadFile(d.CustomScript) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ sshCustomScript += "; " + string(userCustomScript) | |
+ } | |
+ | |
+ task, err = vapp.RunCustomizationScript(d.MachineName, sshCustomScript) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ task, err = vapp.PowerOn() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ log.Infof("Waiting for the VM to power on and run the customization script...") | |
+ | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ log.Infof("Configuring connection") | |
+ | |
+ if d.PublicIP != "0.0.0.0" { | |
+ log.Infof("Creating NAT and Firewall Rules on %s...", d.EdgeGateway) | |
+ task, err = edge.Create1to1Mapping(vapp.VApp.Children.VM[0].NetworkConnectionSection.NetworkConnection.IPAddress, d.PublicIP, d.MachineName) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ log.Infof("Waiting for configuration finish") | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ } else { | |
+ d.PublicIP = vapp.VApp.Children.VM[0].NetworkConnectionSection.NetworkConnection.IPAddress | |
+ } | |
+ | |
+ | |
+ log.Debugf("Disconnecting from vCloud...") | |
+ | |
+ if err = p.VCloudDisconnect(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ // Set VAppID with ID of the created VApp | |
+ d.VAppID = vapp.VApp.ID | |
+ | |
+ log.Infof("Finished Configuration") | |
+ | |
+ d.IPAddress, err = d.GetIP() | |
+ return err | |
+} | |
+ | |
+func (d *Driver) Remove() error { | |
+ p, err := d.NewClient() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ log.Infof("Connecting to vCloud...") | |
+ // Authenticate to vCloud | |
+ v, err := p.VCloudAuthenticate(d.UserName, d.UserPassword, d.ComputeID, d.VDCID) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ // Find our Edge Gateway | |
+ edge, err := v.FindEdgeGateway(d.EdgeGateway) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ vapp, err := v.FindVAppByID(d.VAppID) | |
+ if err != nil { | |
+ log.Infof("Can't find the vApp, assuming it was deleted already...") | |
+ return nil | |
+ } | |
+ | |
+ status, err := vapp.GetStatus() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ var task = govcloudair.Task{} | |
+ | |
+ if d.VDCID != "0" { | |
+ log.Infof("Removing NAT and Firewall Rules on %s...", d.EdgeGateway) | |
+ task, err = edge.Remove1to1Mapping(vapp.VApp.Children.VM[0].NetworkConnectionSection.NetworkConnection.IPAddress, d.PublicIP) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ } | |
+ | |
+ if status == "POWERED_ON" { | |
+ // If it's powered on, power it off before deleting | |
+ log.Infof("Powering Off %s...", d.MachineName) | |
+ task, err = vapp.PowerOff() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ } | |
+ | |
+ log.Debugf("Undeploying %s...", d.MachineName) | |
+ task, err = vapp.Undeploy() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ log.Infof("Deleting %s...", d.MachineName) | |
+ task, err = vapp.Delete() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ if err = p.VCloudDisconnect(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ return nil | |
+ | |
+} | |
+ | |
+func (d *Driver) Start() error { | |
+ | |
+ p, err := d.NewClient() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ log.Infof("Connecting to vCloud...") | |
+ // Authenticate to vCloud | |
+ v, err := p.VCloudAuthenticate(d.UserName, d.UserPassword, d.ComputeID, d.VDCID) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ vapp, err := v.FindVAppByID(d.VAppID) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ status, err := vapp.GetStatus() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ if status == "POWERED_OFF" { | |
+ log.Infof("Starting %s...", d.MachineName) | |
+ task, err := vapp.PowerOn() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ } | |
+ | |
+ if err = p.VCloudDisconnect(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ d.IPAddress, err = d.GetIP() | |
+ return err | |
+} | |
+ | |
+func (d *Driver) Stop() error { | |
+ | |
+ p, err := d.NewClient() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ log.Infof("Connecting to vCloud...") | |
+ // Authenticate to vCloud | |
+ v, err := p.VCloudAuthenticate(d.UserName, d.UserPassword, d.ComputeID, d.VDCID) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ vapp, err := v.FindVAppByID(d.VAppID) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ status, err := vapp.GetStatus() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ if status == "POWERED_ON" { | |
+ log.Infof("Shutting down %s...", d.MachineName) | |
+ task, err := vapp.Shutdown() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ } | |
+ | |
+ if err = p.VCloudDisconnect(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ return nil | |
+ | |
+} | |
+ | |
+func (d *Driver) Restart() error { | |
+ | |
+ p, err := d.NewClient() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ log.Infof("Connecting to vCloud...") | |
+ // Authenticate to vCloud | |
+ v, err := p.VCloudAuthenticate(d.UserName, d.UserPassword, d.ComputeID, d.VDCID) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ vapp, err := v.FindVAppByID(d.VAppID) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ status, err := vapp.GetStatus() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ if status == "POWERED_ON" { | |
+ // If it's powered on, restart the machine | |
+ log.Infof("Restarting %s...", d.MachineName) | |
+ task, err := vapp.Reset() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ } else { | |
+ // If it's not powered on, start it. | |
+ log.Infof("Docker host %s is powered off, powering it back on...", d.MachineName) | |
+ task, err := vapp.PowerOn() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ } | |
+ | |
+ if err = p.VCloudDisconnect(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ d.IPAddress, err = d.GetIP() | |
+ return err | |
+} | |
+ | |
+func (d *Driver) Kill() error { | |
+ p, err := d.NewClient() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ log.Infof("Connecting to vCloud...") | |
+ // Authenticate to vCloud | |
+ v, err := p.VCloudAuthenticate(d.UserName, d.UserPassword, d.ComputeID, d.VDCID) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ vapp, err := v.FindVAppByID(d.VAppID) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ status, err := vapp.GetStatus() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ if status == "POWERED_ON" { | |
+ log.Infof("Stopping %s...", d.MachineName) | |
+ task, err := vapp.PowerOff() | |
+ if err != nil { | |
+ return err | |
+ } | |
+ if err = task.WaitTaskCompletion(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ } | |
+ | |
+ if err = p.VCloudDisconnect(); err != nil { | |
+ return err | |
+ } | |
+ | |
+ return nil | |
+ | |
+} | |
+ | |
+// Helpers | |
+ | |
+func generateVMName() string { | |
+ randomID := utils.TruncateID(utils.GenerateRandomID()) | |
+ return fmt.Sprintf("docker-host-%s", randomID) | |
+} | |
+ | |
+func (d *Driver) createSSHKey() (string, error) { | |
+ if err := ssh.GenerateSSHKey(d.GetSSHKeyPath()); err != nil { | |
+ return "", err | |
+ } | |
+ | |
+ publicKey, err := ioutil.ReadFile(d.publicSSHKeyPath()) | |
+ if err != nil { | |
+ return "", err | |
+ } | |
+ | |
+ return string(publicKey), nil | |
+} | |
+ | |
+func (d *Driver) publicSSHKeyPath() string { | |
+ return d.GetSSHKeyPath() + ".pub" | |
+} | |
Index: drivers/vmwarevcloud/vcloud_test.go | |
IDEA additional info: | |
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP | |
<+>US-ASCII | |
=================================================================== | |
--- drivers/vmwarevcloud/vcloud_test.go (revision 30459c8e8c968f433acf04f21aa7189443031535) | |
+++ drivers/vmwarevcloud/vcloud_test.go (revision 30459c8e8c968f433acf04f21aa7189443031535) | |
@@ -0,0 +1,1 @@ | |
+package vmwarevcloud | |
Index: commands/commands.go | |
IDEA additional info: | |
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP | |
<+>US-ASCII | |
=================================================================== | |
--- commands/commands.go (revision c42545aac4b3ea7577d563fb8c6ba82176b07881) | |
+++ commands/commands.go (revision aae753b432b8dfa2b94f6aa569191440c6f8796e) | |
@@ -25,8 +25,9 @@ | |
_ "github.com/docker/machine/drivers/softlayer" | |
_ "github.com/docker/machine/drivers/virtualbox" | |
_ "github.com/docker/machine/drivers/vmwarefusion" | |
+ _ "github.com/docker/machine/drivers/vmwarevcloud" | |
_ "github.com/docker/machine/drivers/vmwarevcloudair" | |
- _ "github.com/docker/machine/drivers/vmwarevsphere" | |
+// _ "github.com/docker/machine/drivers/vmwarevsphere" | |
"github.com/docker/machine/libmachine" | |
"github.com/docker/machine/libmachine/auth" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment