Skip to content

Instantly share code, notes, and snippets.

@kirmorozov
Created August 23, 2017 10:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kirmorozov/a5989adcea4641694a3fb6c064a3e1e8 to your computer and use it in GitHub Desktop.
Save kirmorozov/a5989adcea4641694a3fb6c064a3e1e8 to your computer and use it in GitHub Desktop.
Patches for docker Machine to Support VCloud Direct 5.6
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
+}
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