Skip to content

Instantly share code, notes, and snippets.

@spareslant
Created September 9, 2016 15:54
Show Gist options
  • Save spareslant/4774569f41c00c41beab4df6c72f29da to your computer and use it in GitHub Desktop.
Save spareslant/4774569f41c00c41beab4df6c72f29da to your computer and use it in GitHub Desktop.
package main
import (
"crypto/rand"
"errors"
"flag"
"fmt"
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/openstack"
"github.com/rackspace/gophercloud/openstack/compute/v2/extensions/floatingip"
"github.com/rackspace/gophercloud/openstack/compute/v2/flavors"
"github.com/rackspace/gophercloud/openstack/compute/v2/images"
"github.com/rackspace/gophercloud/openstack/compute/v2/servers"
"github.com/rackspace/gophercloud/openstack/networking/v2/networks"
"os"
"strconv"
"time"
)
func checkErrorAndExit(err error) {
if err != nil {
fmt.Printf("Error: %v\n", err.Error())
os.Exit(3)
}
}
func checkErrorAndContinue(err error) {
if err != nil {
fmt.Printf("Error: %v\n", err.Error())
}
}
func generateRandomString() string {
b := make([]byte, 8)
_, err := rand.Read(b)
checkErrorAndExit(err)
name := fmt.Sprintf("%X", b[0:4])
return name
}
func getFreeFloatingIP(client *gophercloud.ServiceClient) (*string, error) {
pager := floatingip.List(client)
singlePage, err := pager.AllPages()
checkErrorAndExit(err)
floatingIPList, err := floatingip.ExtractFloatingIPs(singlePage)
checkErrorAndExit(err)
for _, floatingIP := range floatingIPList {
// Check ip floatingIP is assigned to any Instance.
if len(floatingIP.InstanceID) > 0 {
//Do nothing
} else {
return &floatingIP.IP, nil
}
}
return nil, errors.New("ERROR: Free FloatingIP not available.")
}
func assignFloatingIP(client *gophercloud.ServiceClient, id string, ip string) {
fmt.Printf("Attaching floating IP with first VM. It can take a few seconds.\n")
opts := floatingip.AssociateOpts{ServerID: id, FloatingIP: ip}
for {
server, err := servers.Get(client, id).Extract()
checkErrorAndExit(err)
if server.Status == "ACTIVE" {
result := floatingip.AssociateInstance(client, opts)
if result.Err != nil {
fmt.Println(result.Err)
} else {
fmt.Println("Floating IP assigned successfully.")
}
os.Exit(0)
}
time.Sleep(1000 * time.Millisecond)
//fmt.Println(details.Status)
}
}
func main() {
user := flag.String("user", "admin", "OS Username")
pass := flag.String("password", "acf0d596fbb44b1d", "Password")
authUrl := flag.String("authurl", "http://10.0.2.15:5000/v2.0", "AUTH URL")
tenant := flag.String("tenant", "admin", "Tenant Name")
region := flag.String("region", "RegionOne", "Region for VM")
defaultRun := flag.Bool("runwithdefaultvalues", false, "Use this flag to use default values")
image := flag.String("image", "cirros", "Image to be used")
flavor := flag.String("flavor", "m1.tiny", "Size of VM")
network := flag.String("network", "private", "Network for VM")
securityGroup := flag.String("securitygroup", "default", "Security Group for VM")
hostNamePrefix := flag.String("hostnameprefix", generateRandomString(), "Hostname Prefix. default: randomly generated.")
total := flag.String("total", "5", "Total number of instances")
flag.Parse()
os.Setenv("OS_USERNAME", *user)
os.Setenv("OS_PASSWORD", *pass)
os.Setenv("OS_AUTH_URL", *authUrl)
os.Setenv("OS_TENANT_NAME", *tenant)
os.Setenv("OS_REGION_NAME", *region)
if flag.NFlag() == 0 {
flag.PrintDefaults()
os.Exit(1)
} else if *defaultRun == true {
fmt.Println("Creating VMs: ")
} else {
fmt.Println("Creating VMs: ")
}
authOpts, err := openstack.AuthOptionsFromEnv()
checkErrorAndExit(err)
provider, err := openstack.AuthenticatedClient(authOpts)
checkErrorAndExit(err)
otherOpts := gophercloud.EndpointOpts{Region: *region}
client, err := openstack.NewComputeV2(provider, otherOpts)
imageID, err := images.IDFromName(client, *image)
checkErrorAndExit(err)
flavorID, err := flavors.IDFromName(client, *flavor)
checkErrorAndExit(err)
netClient, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{Name: "neutron", Region: *region})
checkErrorAndExit(err)
networkID, err := networks.IDFromName(netClient, *network)
checkErrorAndExit(err)
/* This code is not needed.
securityGroupID, err := getSecurityGroupID(client, *securityGroup)
checkErrorAndExit(err)
fmt.Println(*securityGroupID)
*/
network1 := servers.Network{UUID: networkID, FixedIP: "", Port: ""}
allNetworks := []servers.Network{network1}
noOfInstances, err := strconv.Atoi(*total)
checkErrorAndExit(err)
for i := 1; i <= noOfInstances; i++ {
vmName := *hostNamePrefix + strconv.Itoa(i)
serverCreateOpts := servers.CreateOpts{Name: vmName,
FlavorRef: flavorID,
ImageRef: imageID,
Networks: allNetworks,
UserData: []byte{},
SecurityGroups: []string{*securityGroup}}
_, err := servers.Create(client, serverCreateOpts).Extract()
checkErrorAndContinue(err)
fmt.Printf("%s VM creation request sent successfully.\n Details: { flavor=%s, image=%s, network=%s, sec_group=%s }\n", vmName, *flavor, *image, *network, *securityGroup)
fmt.Println("===================================")
}
vmID, err := servers.IDFromName(client, *hostNamePrefix+strconv.Itoa(1))
checkErrorAndExit(err)
fmt.Printf("Obtaining free floating IP: ")
floatingIP, err := getFreeFloatingIP(client)
checkErrorAndExit(err)
fmt.Printf("%s found.\n", *floatingIP)
assignFloatingIP(client, vmID, *floatingIP)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment