Skip to content

Commit

Permalink
Merge pull request #4283 from mitchellh/openstackhacks
Browse files Browse the repository at this point in the history
builder/openstack: Add image visibility & members
  • Loading branch information
mwhooker authored Dec 15, 2016
2 parents 7097081 + 754ed93 commit 88841cb
Show file tree
Hide file tree
Showing 128 changed files with 4,202 additions and 5,144 deletions.
16 changes: 9 additions & 7 deletions builder/openstack/access_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,16 @@ import (
"net/http"
"os"

"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"github.com/mitchellh/packer/template/interpolate"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack"
)

// AccessConfig is for common configuration related to openstack access
type AccessConfig struct {
Username string `mapstructure:"username"`
UserID string `mapstructure:"user_id"`
Password string `mapstructure:"password"`
APIKey string `mapstructure:"api_key"`
IdentityEndpoint string `mapstructure:"identity_endpoint"`
TenantID string `mapstructure:"tenant_id"`
TenantName string `mapstructure:"tenant_name"`
Expand All @@ -42,9 +41,6 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
}

// Legacy RackSpace stuff. We're keeping this around to keep things BC.
if c.APIKey == "" {
c.APIKey = os.Getenv("SDK_API_KEY")
}
if c.Password == "" {
c.Password = os.Getenv("SDK_PASSWORD")
}
Expand All @@ -71,7 +67,6 @@ func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error {
{&c.Username, &ao.Username},
{&c.UserID, &ao.UserID},
{&c.Password, &ao.Password},
{&c.APIKey, &ao.APIKey},
{&c.IdentityEndpoint, &ao.IdentityEndpoint},
{&c.TenantID, &ao.TenantID},
{&c.TenantName, &ao.TenantName},
Expand Down Expand Up @@ -115,6 +110,13 @@ func (c *AccessConfig) computeV2Client() (*gophercloud.ServiceClient, error) {
})
}

func (c *AccessConfig) imageV2Client() (*gophercloud.ServiceClient, error) {
return openstack.NewImageServiceV2(c.osClient, gophercloud.EndpointOpts{
Region: c.Region,
Availability: c.getEndpointType(),
})
}

func (c *AccessConfig) getEndpointType() gophercloud.Availability {
if c.EndpointType == "internal" || c.EndpointType == "internalURL" {
return gophercloud.AvailabilityInternal
Expand Down
4 changes: 2 additions & 2 deletions builder/openstack/artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"fmt"
"log"

"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack/compute/v2/images"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/images"
)

// Artifact is an artifact implementation that contains built images.
Expand Down
2 changes: 2 additions & 0 deletions builder/openstack/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
&common.StepProvision{},
&StepStopServer{},
&stepCreateImage{},
&stepUpdateImageVisibility{},
&stepAddImageMembers{},
}

// Run!
Expand Down
25 changes: 23 additions & 2 deletions builder/openstack/image_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ package openstack

import (
"fmt"
"strings"

imageservice "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
"github.com/mitchellh/packer/template/interpolate"
)

// ImageConfig is for common configuration related to creating Images.
type ImageConfig struct {
ImageName string `mapstructure:"image_name"`
ImageMetadata map[string]string `mapstructure:"metadata"`
ImageName string `mapstructure:"image_name"`
ImageMetadata map[string]string `mapstructure:"metadata"`
ImageVisibility imageservice.ImageVisibility `mapstructure:"image_visibility"`
ImageMembers []string `mapstructure:"image_members"`
}

func (c *ImageConfig) Prepare(ctx *interpolate.Context) []error {
Expand All @@ -29,6 +33,23 @@ func (c *ImageConfig) Prepare(ctx *interpolate.Context) []error {
c.ImageMetadata["image_type"] = "image"
}

// ImageVisibility values
// https://wiki.openstack.org/wiki/Glance-v2-community-image-visibility-design
if c.ImageVisibility != "" {
validVals := []imageservice.ImageVisibility{"public", "private", "shared", "community"}
valid := false
for _, val := range validVals {
if strings.EqualFold(string(c.ImageVisibility), string(val)) {
valid = true
c.ImageVisibility = val
break
}
}
if !valid {
errs = append(errs, fmt.Errorf("Unknown visibility value %s", c.ImageVisibility))
}
}

if len(errs) > 0 {
return errs
}
Expand Down
12 changes: 5 additions & 7 deletions builder/openstack/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (
"log"
"time"

"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/mitchellh/multistep"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
)

// StateRefreshFunc is a function type used for StateChangeConf that is
Expand Down Expand Up @@ -38,14 +38,12 @@ func ServerStateRefreshFunc(
return func() (interface{}, string, int, error) {
serverNew, err := servers.Get(client, s.ID).Extract()
if err != nil {
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
if ok && errCode.Actual == 404 {
if _, ok := err.(gophercloud.ErrDefault404); ok {
log.Printf("[INFO] 404 on ServerStateRefresh, returning DELETED")
return nil, "DELETED", 0, nil
} else {
log.Printf("[ERROR] Error on ServerStateRefresh: %s", err)
return nil, "", 0, err
}
log.Printf("[ERROR] Error on ServerStateRefresh: %s", err)
return nil, "", 0, err
}

return serverNew, serverNew.Status, serverNew.Progress, nil
Expand Down
8 changes: 4 additions & 4 deletions builder/openstack/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import (
"log"
"time"

"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/mitchellh/multistep"
packerssh "github.com/mitchellh/packer/communicator/ssh"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
"golang.org/x/crypto/ssh"
)

Expand All @@ -31,7 +31,7 @@ func CommHost(
}

// If we have a floating IP, use that
ip := state.Get("access_ip").(*floatingip.FloatingIP)
ip := state.Get("access_ip").(*floatingips.FloatingIP)
if ip != nil && ip.IP != "" {
log.Printf("[DEBUG] Using floating IP %s to connect", ip.IP)
return ip.IP, nil
Expand Down
44 changes: 44 additions & 0 deletions builder/openstack/step_add_image_members.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package openstack

import (
"fmt"

"github.com/gophercloud/gophercloud/openstack/imageservice/v2/members"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
)

type stepAddImageMembers struct{}

func (s *stepAddImageMembers) Run(state multistep.StateBag) multistep.StepAction {
imageId := state.Get("image").(string)
ui := state.Get("ui").(packer.Ui)
config := state.Get("config").(Config)

if len(config.ImageMembers) == 0 {
return multistep.ActionContinue
}

imageClient, err := config.imageV2Client()
if err != nil {
err = fmt.Errorf("Error initializing image service client: %s", err)
state.Put("error", err)
return multistep.ActionHalt
}

for _, member := range config.ImageMembers {
ui.Say(fmt.Sprintf("Adding member '%s' to image %s", member, imageId))
r := members.Create(imageClient, imageId, member)
if _, err = r.Extract(); err != nil {
err = fmt.Errorf("Error adding member to image: %s", err)
state.Put("error", err)
return multistep.ActionHalt
}
}

return multistep.ActionContinue
}

func (s *stepAddImageMembers) Cleanup(multistep.StateBag) {
// No cleanup...
}
16 changes: 9 additions & 7 deletions builder/openstack/step_allocate_ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package openstack
import (
"fmt"

"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/floatingips"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
)

type StepAllocateIp struct {
Expand All @@ -27,7 +27,7 @@ func (s *StepAllocateIp) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}

var instanceIp floatingip.FloatingIP
var instanceIp floatingips.FloatingIP

// This is here in case we error out before putting instanceIp into the
// statebag below, because it is requested by Cleanup()
Expand All @@ -38,7 +38,7 @@ func (s *StepAllocateIp) Run(state multistep.StateBag) multistep.StepAction {
} else if s.FloatingIpPool != "" {
ui.Say(fmt.Sprintf("Creating floating IP..."))
ui.Message(fmt.Sprintf("Pool: %s", s.FloatingIpPool))
newIp, err := floatingip.Create(client, floatingip.CreateOpts{
newIp, err := floatingips.Create(client, floatingips.CreateOpts{
Pool: s.FloatingIpPool,
}).Extract()
if err != nil {
Expand All @@ -55,7 +55,9 @@ func (s *StepAllocateIp) Run(state multistep.StateBag) multistep.StepAction {
if instanceIp.IP != "" {
ui.Say(fmt.Sprintf("Associating floating IP with server..."))
ui.Message(fmt.Sprintf("IP: %s", instanceIp.IP))
err := floatingip.Associate(client, server.ID, instanceIp.IP).ExtractErr()
err := floatingips.AssociateInstance(client, server.ID, floatingips.AssociateOpts{
FloatingIP: instanceIp.IP,
}).ExtractErr()
if err != nil {
err := fmt.Errorf(
"Error associating floating IP %s with instance: %s",
Expand All @@ -76,7 +78,7 @@ func (s *StepAllocateIp) Run(state multistep.StateBag) multistep.StepAction {
func (s *StepAllocateIp) Cleanup(state multistep.StateBag) {
config := state.Get("config").(Config)
ui := state.Get("ui").(packer.Ui)
instanceIp := state.Get("access_ip").(*floatingip.FloatingIP)
instanceIp := state.Get("access_ip").(*floatingips.FloatingIP)

// We need the v2 compute client
client, err := config.computeV2Client()
Expand All @@ -87,7 +89,7 @@ func (s *StepAllocateIp) Cleanup(state multistep.StateBag) {
}

if s.FloatingIpPool != "" && instanceIp.ID != "" {
if err := floatingip.Delete(client, instanceIp.ID).ExtractErr(); err != nil {
if err := floatingips.Delete(client, instanceIp.ID).ExtractErr(); err != nil {
ui.Error(fmt.Sprintf(
"Error deleting temporary floating IP %s", instanceIp.IP))
return
Expand Down
8 changes: 4 additions & 4 deletions builder/openstack/step_create_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import (
"log"
"time"

"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/images"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack/compute/v2/images"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
)

type stepCreateImage struct{}
Expand Down Expand Up @@ -68,7 +68,7 @@ func WaitForImage(client *gophercloud.ServiceClient, imageId string) error {
for {
image, err := images.Get(client, imageId).Extract()
if err != nil {
errCode, ok := err.(*gophercloud.UnexpectedResponseCodeError)
errCode, ok := err.(*gophercloud.ErrUnexpectedResponseCode)
if ok && (errCode.Actual == 500 || errCode.Actual == 404) {
numErrors++
if numErrors >= maxNumErrors {
Expand Down
2 changes: 1 addition & 1 deletion builder/openstack/step_get_password.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import (
"log"
"time"

"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/helper/communicator"
"github.com/mitchellh/packer/packer"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
"golang.org/x/crypto/ssh"
)

Expand Down
2 changes: 1 addition & 1 deletion builder/openstack/step_key_pair.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ import (
"os/exec"
"runtime"

"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/common/uuid"
"github.com/mitchellh/packer/packer"
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
"golang.org/x/crypto/ssh"
)

Expand Down
4 changes: 2 additions & 2 deletions builder/openstack/step_load_extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"fmt"
"log"

"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions"
"github.com/gophercloud/gophercloud/pagination"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions"
"github.com/rackspace/gophercloud/pagination"
)

// StepLoadExtensions gets the FlavorRef from a Flavor. It first assumes
Expand Down
2 changes: 1 addition & 1 deletion builder/openstack/step_load_flavor.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"fmt"
"log"

"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
)

// StepLoadFlavor gets the FlavorRef from a Flavor. It first assumes
Expand Down
6 changes: 3 additions & 3 deletions builder/openstack/step_run_source_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import (
"io/ioutil"
"log"

"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/keypairs"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
)

type StepRunSourceServer struct {
Expand Down Expand Up @@ -63,7 +63,7 @@ func (s *StepRunSourceServer) Run(state multistep.StateBag) multistep.StepAction
Networks: networks,
AvailabilityZone: s.AvailabilityZone,
UserData: userData,
ConfigDrive: s.ConfigDrive,
ConfigDrive: &s.ConfigDrive,
}

var serverOptsExt servers.CreateOptsBuilder
Expand Down
4 changes: 2 additions & 2 deletions builder/openstack/step_stop_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package openstack
import (
"fmt"

"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/startstop"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/packer"
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/startstop"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
)

type StepStopServer struct{}
Expand Down
Loading

0 comments on commit 88841cb

Please sign in to comment.