Create an ALS tool to upload a specific image onto HP cloud.
Change-Id: Icb152246e202fbd57baf447fef04a1d727e45e0a
This commit is contained in:
parent
03aa5209e0
commit
191b33041c
|
@ -0,0 +1,260 @@
|
|||
// server.go
|
||||
package compute
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.openstack.org/stackforge/golang-client.git/misc"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"time"
|
||||
)
|
||||
|
||||
type serversResp struct {
|
||||
ServerInfos []ServerInfo `json:"servers"`
|
||||
}
|
||||
|
||||
type serversDetailResp struct {
|
||||
ServerInfoDetails []ServerInfoDetail `json:"servers"`
|
||||
}
|
||||
|
||||
type serverDetailResp struct {
|
||||
ServerInfoDetail ServerInfoDetail `json:"server"`
|
||||
}
|
||||
|
||||
type ServerInfo struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Links []Link `json:"links"`
|
||||
}
|
||||
|
||||
type ServerInfoDetail struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Status string `json:"status"`
|
||||
Created *time.Time `json:"created"`
|
||||
Updated *time.Time `json:"updated"`
|
||||
HostId string `json:"hostId"`
|
||||
Addresses map[string][]Address `json:"addresses"`
|
||||
Links []Link `json:"links"`
|
||||
Image Image `json:"image"`
|
||||
Flavor Flavor `json:"flavor"`
|
||||
TaskState string `json:"OS-EXT-STS:task_state"`
|
||||
VMState string `json:"OS-EXT-STS:vm_state"`
|
||||
PowerState int `json:"OS-EXT-STS:power_state"`
|
||||
AvailabilityZone string `json:"OS-EXT-AZ:availability_zone:"`
|
||||
UserId string `json:"user_id"`
|
||||
TenantId string `json:"tenant_id"`
|
||||
AccessIPv4 string `json:"accessIPv4"`
|
||||
AccessIPv6 string `json:"accessIPv6"`
|
||||
ConfigDrive string `json:"config_drive"`
|
||||
Progress int `json:"progress"`
|
||||
MetaData map[string]string `json:"metadata"`
|
||||
AdminPass string `json:"adminPass"`
|
||||
}
|
||||
|
||||
type Link struct {
|
||||
HRef string `json:"href"`
|
||||
Rel string `json:"rel"`
|
||||
}
|
||||
|
||||
type Image struct {
|
||||
Id string `json:"id"`
|
||||
Links []Link `json:"links"`
|
||||
}
|
||||
|
||||
type Flavor struct {
|
||||
Id string `json:"id"`
|
||||
Links []Link `json:"links"`
|
||||
}
|
||||
|
||||
type SecurityGroups struct {
|
||||
SecurityGroups []SecurityGroup `json:"security_groups"`
|
||||
}
|
||||
|
||||
type SecurityGroup struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type Address struct {
|
||||
Addr string `json:"addr"`
|
||||
Version int `json:"version"`
|
||||
Type string `json:"OS-EXT-IPS:type"`
|
||||
MacAddr string `json:"OS-EXT-IPS-MAC:mac_addr"`
|
||||
}
|
||||
|
||||
type ByName []ServerInfo
|
||||
|
||||
func (a ByName) Len() int { return len(a) }
|
||||
func (a ByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a ByName) Less(i, j int) bool { return a[i].Name < a[j].Name }
|
||||
|
||||
func GetServerInfos(url string, token string) (serverInfos []ServerInfo, err error) {
|
||||
|
||||
_, body, err := misc.CallGetAPI(url+"/servers", "X-Auth-Token", token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var sr = serversResp{}
|
||||
if err = json.Unmarshal([]byte(body), &sr); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
serverInfos = sr.ServerInfos
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
|
||||
func GetServerInfoDetails(url string, token string) (serverInfoDetails []ServerInfoDetail, err error) {
|
||||
|
||||
_, body, err := misc.CallGetAPI(url+"/servers/detail", "X-Auth-Token", token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var sr = serversDetailResp{}
|
||||
if err = json.Unmarshal(body, &sr); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
serverInfoDetails = sr.ServerInfoDetails
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
|
||||
func GetServerInfoDetail(url string, token string, id string) (serverInfoDetail ServerInfoDetail, err error) {
|
||||
reqUrl := fmt.Sprintf("%s/servers/%s", url, id)
|
||||
_, body, err := misc.CallGetAPI(reqUrl, "X-Auth-Token", token)
|
||||
if err != nil {
|
||||
return serverInfoDetail, err
|
||||
}
|
||||
|
||||
serverDetailResp := serverDetailResp{}
|
||||
if err = json.Unmarshal(body, &serverDetailResp); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
serverInfoDetail = serverDetailResp.ServerInfoDetail
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
|
||||
func DeleteServer(url string, token string, id string) (err error) {
|
||||
reqUrl := fmt.Sprintf("%s/servers/%s", url, id)
|
||||
err = misc.CallDeleteAPI(reqUrl, "X-Auth-Token", token)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
|
||||
type ServerNetworkParameters struct {
|
||||
Uuid string `json:"uuid"`
|
||||
Port string `json:"port"`
|
||||
}
|
||||
|
||||
type ServerServiceParameters struct {
|
||||
Name string `json:"name"`
|
||||
ImageRef string `json:"imageRef"`
|
||||
SSHKey string `json:"sshkey"`
|
||||
FlavorRef int32 `json:"flavorRef"`
|
||||
MaxCount int32 `json:"maxcount"`
|
||||
MinCount int32 `json:"mincount"`
|
||||
UserData string `json:"userdata"`
|
||||
Networks []ServerNetworkParameters `json:"networks"`
|
||||
SecurityGroup []SecurityGroup `json:"securitygroups"`
|
||||
}
|
||||
|
||||
type ServerRequestInfo map[string]ServerServiceParameters
|
||||
|
||||
type ServerService struct {
|
||||
Url string `json:"url"`
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
func CreateServer(client *http.Client, ss ServerService, serverRequestInfo ServerRequestInfo) (serverInfoDetail ServerInfoDetail, err error) {
|
||||
|
||||
reqBody, err := json.Marshal(serverRequestInfo)
|
||||
if err != nil {
|
||||
return serverInfoDetail, err
|
||||
}
|
||||
|
||||
reqUrl := ss.Url + "/servers"
|
||||
|
||||
req, err := http.NewRequest("POST", reqUrl, bytes.NewReader(reqBody))
|
||||
if err != nil {
|
||||
return serverInfoDetail, err
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Accept", "application/json")
|
||||
req.Header.Set("X-Auth-Token", ss.Token)
|
||||
|
||||
misc.LogDebug("CreateServer-----------------------------------httputil.DumpRequestOut-------BEGIN")
|
||||
dumpReqByte, err := httputil.DumpRequestOut(req, true)
|
||||
if err != nil {
|
||||
log.Printf(err.Error())
|
||||
}
|
||||
misc.LogDebug(string(dumpReqByte))
|
||||
misc.LogDebug("CreateServer-----------------------------------httputil.DumpRequestOut-------END")
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
log.Printf(err.Error())
|
||||
}
|
||||
|
||||
misc.LogDebug("CreateServer-----------------------------------httputil.DumpResponse-------BEGIN")
|
||||
dumpRspByte, err := httputil.DumpResponse(resp, true)
|
||||
if err != nil {
|
||||
log.Printf(err.Error())
|
||||
}
|
||||
misc.LogDebug(string(dumpRspByte))
|
||||
misc.LogDebug("CreateServer-----------------------------------httputil.DumpResponse-------END")
|
||||
|
||||
if err != nil {
|
||||
return serverInfoDetail, err
|
||||
}
|
||||
|
||||
err = json.NewDecoder(resp.Body).Decode(&serverInfoDetail)
|
||||
defer resp.Body.Close()
|
||||
|
||||
if !(resp.StatusCode == 201 || resp.StatusCode == 202) {
|
||||
err = errors.New(fmt.Sprintf("Error: status code != 201 or 202, object not created. Status: (%s), reqUrl: %s, reqBody: %s, resp: %s, respBody: %s",
|
||||
resp.Status, reqUrl, reqBody, resp, resp.Body))
|
||||
|
||||
log.Printf(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
|
||||
func ServerAction(url string, token string, id string, action string, key string, value string) (err error) {
|
||||
var reqBody = []byte(fmt.Sprintf(`
|
||||
{
|
||||
"%s":
|
||||
{
|
||||
"%s": "%s"
|
||||
}
|
||||
}`, action, key, value))
|
||||
|
||||
resp, err := misc.CallAPI("POST", url+"/servers/"+id+"/action", &reqBody, "X-Auth-Token", token)
|
||||
|
||||
if err = misc.CheckHttpResponseStatusCode(resp); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = nil
|
||||
return
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package compute_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"git.openstack.org/stackforge/golang-client.git/Compute/v2"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCreateServer(t *testing.T) {
|
||||
|
||||
now := time.Now()
|
||||
|
||||
var serverInfoDetail = compute.ServerInfoDetail{
|
||||
"my_server_id_1",
|
||||
"my_server_name_1",
|
||||
"my_server_status_1",
|
||||
&now, // created time
|
||||
&now, // updated time
|
||||
"my_server_hostId_1",
|
||||
make(map[string][]compute.Address),
|
||||
[]compute.Link{{"href_1", "rel_1"}, {"href_2", "rel_2"}},
|
||||
compute.Image{"image_id1", []compute.Link{{"href_1", "rel_1"}, {"href_2", "rel_2"}}},
|
||||
compute.Flavor{"image_id1", []compute.Link{{"href_1", "rel_1"}, {"href_2", "rel_2"}}},
|
||||
"my_OS-EXT-STS_task_state_1",
|
||||
"my_OS-EXT-STS_vm_state_1",
|
||||
1, // PowerState
|
||||
"my_zone_a",
|
||||
"my_user_id_1",
|
||||
"my_tenant_id_1",
|
||||
"192.168.0.12",
|
||||
"my_accessIPv6_1",
|
||||
"my_config_drive_1",
|
||||
2, // Progress
|
||||
make(map[string]string),
|
||||
"my_adminPass_1",
|
||||
}
|
||||
|
||||
marshaledserverInfoDetail, err := json.Marshal(serverInfoDetail)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
var apiServer = httptest.NewServer(http.HandlerFunc(
|
||||
func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "POST" {
|
||||
w.Header().Set("Version", "my_server_version.1.0.0")
|
||||
w.WriteHeader(201)
|
||||
w.Write([]byte(marshaledserverInfoDetail))
|
||||
return
|
||||
}
|
||||
t.Error(errors.New("Failed: r.Method == POST"))
|
||||
}))
|
||||
defer apiServer.Close()
|
||||
|
||||
serverService := compute.ServerService{
|
||||
apiServer.URL,
|
||||
"my_token"}
|
||||
|
||||
var serverServiceParameters = compute.ServerServiceParameters{
|
||||
"my_server",
|
||||
"8c3cd338-1282-4fbb-bbaf-2256ff97c7b7", // imageRef
|
||||
"my_key_name",
|
||||
101, // flavorRef
|
||||
1, // maxcount
|
||||
1, // mincount
|
||||
"my_user_data",
|
||||
[]compute.ServerNetworkParameters{
|
||||
compute.ServerNetworkParameters{"1111d337-0282-4fbb-bbaf-2256ff97c7b7", "881"},
|
||||
compute.ServerNetworkParameters{"2222d337-0282-4fbb-bbaf-2256ff97c7b7", "882"},
|
||||
compute.ServerNetworkParameters{"3333d337-0282-4fbb-bbaf-2256ff97c7b7", "883"}},
|
||||
[]compute.SecurityGroup{
|
||||
compute.SecurityGroup{"my_security_group_123"},
|
||||
compute.SecurityGroup{"my_security_group_456"}}}
|
||||
|
||||
var serverRequestInfo = make(compute.ServerRequestInfo)
|
||||
serverRequestInfo["server"] = serverServiceParameters
|
||||
|
||||
result, err := compute.CreateServer(new(http.Client), serverService, serverRequestInfo)
|
||||
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(result, serverInfoDetail) {
|
||||
t.Error(errors.New("Failed: result != expected serverInfoDetail"))
|
||||
}
|
||||
|
||||
err = nil
|
||||
return
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
hosts:
|
||||
test-server-1:
|
||||
ip: 10.0.0.91
|
||||
ismaster: true
|
||||
|
||||
imageRef: 261844b3-479c-5446-a2c4-1ea95d53b668
|
||||
sshkey: Go1_KeyPair
|
||||
flavorref: 101
|
||||
maxcount: 1
|
||||
mincount: 1
|
||||
userdata:
|
|
@ -0,0 +1,75 @@
|
|||
// keypair.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"git.openstack.org/stackforge/golang-client.git/identity/v2"
|
||||
"git.openstack.org/stackforge/golang-client.git/misc"
|
||||
|
||||
"github.com/parnurzeal/gorequest"
|
||||
)
|
||||
|
||||
type keyPairsResp struct {
|
||||
KeyPairs []Keypair `josn:"keypairs"`
|
||||
}
|
||||
|
||||
type Keypair struct {
|
||||
KeyPair KeyPairEntry `json:"keypair"`
|
||||
}
|
||||
|
||||
type KeyPairEntry struct {
|
||||
Name string `json:"name"`
|
||||
PublicKey string `json:"public_key"`
|
||||
FingerPrint string `json:"fingerprint"`
|
||||
}
|
||||
|
||||
func GetKeypairs(url string, token identity.Token) (keypairs []Keypair, err error) {
|
||||
|
||||
req := gorequest.New()
|
||||
|
||||
resp, body, errs := req.Get(url+"/os-keypairs").
|
||||
Set("Content-Type", "application/json").
|
||||
Set("Accept", "application/json").
|
||||
Set("X-Auth-Token", token.Id).
|
||||
End()
|
||||
|
||||
if err = misc.CheckHttpResponseStatusCode(resp); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if errs != nil {
|
||||
err = errs[len(errs)-1]
|
||||
return
|
||||
}
|
||||
|
||||
var kp = keyPairsResp{}
|
||||
if err = json.Unmarshal([]byte(body), &kp); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
keypairs = kp.KeyPairs
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
|
||||
func GetKeypair(url string, token identity.Token, name string) (keypair KeyPairEntry, err error) {
|
||||
|
||||
keypairs, err := GetKeypairs(url, token)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range keypairs {
|
||||
if v.KeyPair.Name == name {
|
||||
keypair = v.KeyPair
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
err = errors.New(fmt.Sprintf("keypair %s not found", name))
|
||||
return
|
||||
}
|
|
@ -0,0 +1,259 @@
|
|||
// AlsTool project main.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"git.openstack.org/stackforge/golang-client.git/Compute/v2"
|
||||
"git.openstack.org/stackforge/golang-client.git/misc"
|
||||
"git.openstack.org/stackforge/golang-client.git/network/v2"
|
||||
"gopkg.in/yaml.v1"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var (
|
||||
configFile string
|
||||
authUrl string
|
||||
tenantId string
|
||||
tenantName string
|
||||
username string
|
||||
password string
|
||||
uninstall bool
|
||||
cloudConfig bool
|
||||
install bool
|
||||
status bool
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Nodes map[string]Node `yaml:"hosts"`
|
||||
ImageRef string `yaml:"imageRef"`
|
||||
SSHKey string `yaml:"sshkey"`
|
||||
FlavorRef string `json:"flavorref"`
|
||||
MaxCount string `json:"maxcount"`
|
||||
MinCount string `json:"mincount"`
|
||||
UserData string `json:"userdata"`
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
IP string `yaml:"ip"`
|
||||
IsMaster bool `yaml:"ismaster"`
|
||||
ServerId string
|
||||
}
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&configFile, "c", "config.yml", "ALS tool configuration file")
|
||||
flag.StringVar(&authUrl, "a", "", "OpenStack authentication URL (OS_AUTH_URL)")
|
||||
flag.StringVar(&tenantId, "i", "", "OpenStack tenant id (OS_TENANT_ID)")
|
||||
flag.StringVar(&tenantName, "n", "", "OpenStack tenant name (OS_TENANT_NAME)")
|
||||
flag.StringVar(&username, "u", "", "OpenStack user name (OS_USERNAME)")
|
||||
flag.StringVar(&password, "p", "", "OpenStack passsword (OS_PASSWORD)")
|
||||
flag.BoolVar(&uninstall, "U", false, "Uninstall cluster (defined in config file -c)")
|
||||
flag.BoolVar(&cloudConfig, "C", false, "Create CloudConfig files for cluster")
|
||||
flag.BoolVar(&install, "I", false, "Install cluster (defined in config file -c)")
|
||||
flag.BoolVar(&status, "S", false, "Cluster status (defined in config file -c)")
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
config, err := readConfigFile(configFile)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
config.Log()
|
||||
|
||||
openStackConfig, err := InitializeFromEnv()
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
updateConfigFromCommandLine(&openStackConfig)
|
||||
openStackConfig.Log()
|
||||
|
||||
auth, err := Authenticate(openStackConfig)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
token := auth.Access.Token
|
||||
log.Printf("%-20s - %s\n", "token:", token.Id)
|
||||
|
||||
endpointList := auth.EndpointList()
|
||||
|
||||
subnets, err := network.GetSubnets(endpointList["network"], token.Id)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("%-20s - %s\n", "error:", err.Error()))
|
||||
}
|
||||
|
||||
ports, err := network.GetPorts(endpointList["network"], token.Id)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("%-20s - %s\n", "error:", err.Error()))
|
||||
}
|
||||
sort.Sort(network.ByName(ports))
|
||||
|
||||
servers, err := compute.GetServerInfos(endpointList["compute"], token.Id)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("%-20s - %s\n", "error:", err.Error()))
|
||||
}
|
||||
sort.Sort(compute.ByName(servers))
|
||||
|
||||
// uninstall/cleanup
|
||||
for _, v := range servers {
|
||||
|
||||
if _, ok := config.Nodes[v.Name]; ok {
|
||||
|
||||
log.Printf("%-20s - %s\n", "delete server", v.Name)
|
||||
|
||||
err := compute.DeleteServer(endpointList["compute"], token.Id, v.Id)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("%-20s - %s\n", "error:", err.Error()))
|
||||
}
|
||||
|
||||
log.Printf("%-20s - %s %s\n", "delete server", v.Name, "COMPLETED")
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range ports {
|
||||
|
||||
if _, ok := config.Nodes[v.Name]; ok {
|
||||
|
||||
log.Printf("%-20s - %s\n", "delete port", v.Name)
|
||||
|
||||
err := network.DeletePort(endpointList["network"], token.Id, v.Id)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("%-20s - %s\n", "error:", err.Error()))
|
||||
}
|
||||
|
||||
log.Printf("%-20s - %s %s\n", "delete port", v.Name, "COMPLETED")
|
||||
}
|
||||
}
|
||||
|
||||
flavorRef, err := strconv.Atoi(config.FlavorRef)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("%-20s - %s\n", "error:", err.Error()))
|
||||
}
|
||||
|
||||
maxCount, err := strconv.Atoi(config.MaxCount)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("%-20s - %s\n", "error:", err.Error()))
|
||||
}
|
||||
|
||||
minCount, err := strconv.Atoi(config.MinCount)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("%-20s - %s\n", "error:", err.Error()))
|
||||
}
|
||||
|
||||
//install
|
||||
for hostname, hostnode := range config.Nodes {
|
||||
|
||||
log.Printf("%-20s - %s %s\n", "create port", hostname, hostnode.IP)
|
||||
port, err := network.CreatePort(endpointList["network"], token.Id, hostname, hostnode.IP, subnets[0])
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("%-20s - %s\n", "error:", err.Error()))
|
||||
}
|
||||
log.Printf("%-20s - %s %s\n", "create port", port.Id, "COMPLETED")
|
||||
|
||||
log.Printf("%-20s - %s %s\n", "create server", hostname, hostnode.IP)
|
||||
|
||||
serverService := compute.ServerService{
|
||||
endpointList["compute"],
|
||||
token.Id}
|
||||
|
||||
var serverServiceParameters = compute.ServerServiceParameters{
|
||||
hostname,
|
||||
config.ImageRef,
|
||||
config.SSHKey,
|
||||
int32(flavorRef),
|
||||
int32(maxCount),
|
||||
int32(minCount),
|
||||
config.UserData,
|
||||
[]compute.ServerNetworkParameters{
|
||||
compute.ServerNetworkParameters{port.NetworkId, port.Id}},
|
||||
[]compute.SecurityGroup{
|
||||
compute.SecurityGroup{"default"}}}
|
||||
|
||||
var serverRequestInfo = make(compute.ServerRequestInfo)
|
||||
serverRequestInfo["server"] = serverServiceParameters
|
||||
|
||||
result, err := compute.CreateServer(new(http.Client), serverService, serverRequestInfo)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("%-20s - %s\n", "error:", err.Error()))
|
||||
}
|
||||
|
||||
marshaledResult, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Sprintf("%-20s - %s\n", "error:", err.Error()))
|
||||
}
|
||||
misc.LogDebug("Result = " + string(marshaledResult))
|
||||
|
||||
log.Printf("%-20s - %s %s %s\n", "create server", hostname, hostnode.IP, "COMPLETED")
|
||||
}
|
||||
|
||||
err = nil
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func updateConfigFromCommandLine(config *OpenStackConfig) {
|
||||
|
||||
if len(authUrl) > 0 {
|
||||
config.AuthUrl = authUrl
|
||||
}
|
||||
if len(tenantId) > 0 {
|
||||
config.TenantId = tenantId
|
||||
}
|
||||
if len(tenantName) > 0 {
|
||||
config.TenantName = tenantName
|
||||
}
|
||||
if len(username) > 0 {
|
||||
config.Username = username
|
||||
}
|
||||
if len(password) > 0 {
|
||||
config.Password = password
|
||||
}
|
||||
}
|
||||
|
||||
func readConfigFile(filename string) (config Config, err error) {
|
||||
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = yaml.Unmarshal(b, &config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
|
||||
func (config Config) Log() {
|
||||
for k, v := range config.Nodes {
|
||||
log.Printf("%-20s - %s %v\n", "config file", k, v)
|
||||
}
|
||||
log.Printf("%-20s - %s %s\n", "config file", "ImageRef", config.ImageRef)
|
||||
log.Printf("%-20s - %s %s\n", "config file", "SSHKey", config.SSHKey)
|
||||
log.Printf("%-20s - %s %s\n", "config file", "FlavorRef", config.FlavorRef)
|
||||
log.Printf("%-20s - %s %s\n", "config file", "MaxCount", config.MaxCount)
|
||||
log.Printf("%-20s - %s %s\n", "config file", "MinCount", config.MinCount)
|
||||
log.Printf("%-20s - %s %s\n", "config file", "UserData", config.UserData)
|
||||
}
|
||||
|
||||
func getUserData(filename string) (encodedStr string, err error) {
|
||||
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
encodedStr = base64.StdEncoding.EncodeToString(b)
|
||||
err = nil
|
||||
return
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
// AlsTool project openstackconfig.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.openstack.org/stackforge/golang-client.git/identity/v2"
|
||||
"github.com/parnurzeal/gorequest"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type OpenStackConfig struct {
|
||||
AuthUrl string
|
||||
TenantId string
|
||||
TenantName string
|
||||
Username string
|
||||
Password string
|
||||
DebugOpenStack bool
|
||||
}
|
||||
|
||||
type Links struct {
|
||||
Links []Link `json:"links"`
|
||||
}
|
||||
|
||||
type Link struct {
|
||||
href string `json:"href"`
|
||||
rel string `json:"rel"`
|
||||
}
|
||||
|
||||
func (config OpenStackConfig) Log() {
|
||||
log.Printf("%-20s - %s\n", "OS_AUTH_URL", config.AuthUrl)
|
||||
log.Printf("%-20s - %s\n", "OS_TENANT_ID", config.TenantId)
|
||||
log.Printf("%-20s - %s\n", "OS_TENANT_NAME", config.TenantName)
|
||||
log.Printf("%-20s - %s\n", "OS_USERNAME", config.Username)
|
||||
}
|
||||
|
||||
func InitializeFromEnv() (config OpenStackConfig, err error) {
|
||||
|
||||
var c = OpenStackConfig{}
|
||||
|
||||
c.AuthUrl = os.Getenv("OS_AUTH_URL")
|
||||
c.TenantId = os.Getenv("OS_TENANT_ID")
|
||||
c.TenantName = os.Getenv("OS_TENANT_NAME")
|
||||
c.Username = os.Getenv("OS_USERNAME")
|
||||
c.Password = os.Getenv("OS_PASSWORD")
|
||||
|
||||
if len(c.AuthUrl) == 0 {
|
||||
err = errors.New("Error: no authentication URL specified")
|
||||
return
|
||||
}
|
||||
if len(c.Username) == 0 {
|
||||
err = errors.New("Error: no username specified")
|
||||
return
|
||||
}
|
||||
if len(c.Password) == 0 {
|
||||
err = errors.New("Error: no password specified")
|
||||
return
|
||||
}
|
||||
if len(c.TenantName) == 0 {
|
||||
err = errors.New("Error: no tenant name specified")
|
||||
return
|
||||
}
|
||||
if len(c.TenantId) == 0 {
|
||||
err = errors.New("Error: no tenant ID specified")
|
||||
return
|
||||
}
|
||||
|
||||
c.DebugOpenStack = false
|
||||
if len(os.Getenv("DebugOpenStack")) != 0 {
|
||||
c.DebugOpenStack = true
|
||||
}
|
||||
|
||||
config = c
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
|
||||
func Authenticate(openStackConfig OpenStackConfig) (auth identity.Auth, err error) {
|
||||
|
||||
req := gorequest.New()
|
||||
|
||||
reqUrl := fmt.Sprintf("%s/tokens", openStackConfig.AuthUrl)
|
||||
|
||||
reqBody := fmt.Sprintf(`
|
||||
{"auth":
|
||||
{
|
||||
"passwordCredentials":
|
||||
{
|
||||
"username":"%s",
|
||||
"password":"%s"
|
||||
},
|
||||
"tenantName":"%s"
|
||||
}
|
||||
}`, openStackConfig.Username, openStackConfig.Password, openStackConfig.TenantName)
|
||||
|
||||
_, body, errs := req.Post(reqUrl).
|
||||
Set(`Accept-Encoding`, `gzip,deflate`).
|
||||
Set(`Accept`, `application/json`).
|
||||
Set(`Content-Type`, `application/json`).
|
||||
Send(reqBody).
|
||||
End()
|
||||
|
||||
if errs != nil {
|
||||
err = errs[len(errs)-1]
|
||||
return
|
||||
}
|
||||
|
||||
if err = json.Unmarshal([]byte(body), &auth); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !auth.Access.Token.Expires.After(time.Now()) {
|
||||
err = errors.New("Error: The AuthN token is expired")
|
||||
return
|
||||
}
|
||||
|
||||
err = nil
|
||||
return
|
||||
}
|
|
@ -153,3 +153,18 @@ func auth(url, jsonStr *string) (Auth, error) {
|
|||
}
|
||||
return auth, nil
|
||||
}
|
||||
|
||||
func (auth Auth) EndpointList() (list map[string]string) {
|
||||
|
||||
list = make(map[string]string)
|
||||
|
||||
for _, v := range auth.Access.ServiceCatalog {
|
||||
for _, endPoint := range v.Endpoints {
|
||||
if endPoint.Region == "region-b.geo-1" {
|
||||
list[v.Type] = endPoint.PublicURL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
|
77
misc/util.go
77
misc/util.go
|
@ -18,9 +18,39 @@ import (
|
|||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"os"
|
||||
)
|
||||
|
||||
var zeroByte = &([]byte{}) //pointer to empty []byte
|
||||
|
||||
func CallDeleteAPI(url string, h ...string) (err error) {
|
||||
resp, err := CallAPI("DELETE", url, zeroByte, h...)
|
||||
|
||||
return CheckHttpResponseStatusCode(resp)
|
||||
}
|
||||
|
||||
func CallGetAPI(url string, h ...string) (header http.Header, responseByteArr []byte, err error) {
|
||||
resp, err := CallAPI("GET", url, zeroByte, h...)
|
||||
header = resp.Header
|
||||
|
||||
if err = CheckHttpResponseStatusCode(resp); err != nil {
|
||||
return header, nil, err
|
||||
}
|
||||
|
||||
responseByteArr, err = ioutil.ReadAll(resp.Body)
|
||||
defer resp.Body.Close()
|
||||
|
||||
if err != nil {
|
||||
return header, responseByteArr, err
|
||||
}
|
||||
|
||||
return header, responseByteArr, nil
|
||||
}
|
||||
|
||||
//CallAPI sends an HTTP request using "method" to "url".
|
||||
//For uploading / sending file, caller needs to set the "content". Otherwise,
|
||||
//set it to zero length []byte. If Header fields need to be set, then set it in
|
||||
|
@ -45,21 +75,46 @@ func CallAPI(method, url string, content *[]byte, h ...string) (*http.Response,
|
|||
//comment it out, if you are confident in your test suites.
|
||||
var req *http.Request
|
||||
var err error
|
||||
req, err = http.NewRequest(method, url, nil)
|
||||
contentLength := int64(len(*content))
|
||||
if contentLength > 0 {
|
||||
req, err = http.NewRequest(method, url, bytes.NewReader(*content))
|
||||
//req.Body = *(new(io.ReadCloser)) //these 3 lines do not work but I am
|
||||
//req.Body.Read(content) //keeping them here in case I wonder why
|
||||
//req.Body.Close() //I did not implement it this way :)
|
||||
} else {
|
||||
req, err = http.NewRequest(method, url, nil)
|
||||
}
|
||||
req.ContentLength = contentLength
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(h)-1; i = i + 2 {
|
||||
req.Header.Set(h[i], h[i+1])
|
||||
}
|
||||
req.ContentLength = int64(len(*content))
|
||||
if req.ContentLength > 0 {
|
||||
req.Body = readCloser{bytes.NewReader(*content)}
|
||||
//req.Body = *(new(io.ReadCloser)) //these 3 lines do not work but I am
|
||||
//req.Body.Read(content) //keeping them here in case I wonder why
|
||||
//req.Body.Close() //I did not implement it this way :)
|
||||
|
||||
LogDebug("CallAPI-----------------------------------httputil.DumpRequestOut-------BEGIN")
|
||||
dumpReqByte, err := httputil.DumpRequestOut(req, true)
|
||||
if err != nil {
|
||||
log.Printf(err.Error())
|
||||
}
|
||||
return (new(http.Client)).Do(req)
|
||||
LogDebug(string(dumpReqByte))
|
||||
LogDebug("CallAPI-----------------------------------httputil.DumpRequestOut-------END")
|
||||
|
||||
resp, err := (new(http.Client)).Do(req)
|
||||
if err != nil {
|
||||
log.Printf(err.Error())
|
||||
}
|
||||
|
||||
LogDebug("CallAPI-----------------------------------httputil.DumpResponse-------BEGIN")
|
||||
dumpRspByte, err := httputil.DumpResponse(resp, true)
|
||||
if err != nil {
|
||||
log.Printf(err.Error())
|
||||
}
|
||||
LogDebug(string(dumpRspByte))
|
||||
LogDebug("CallAPI-----------------------------------httputil.DumpResponse-------END")
|
||||
|
||||
return resp, err
|
||||
}
|
||||
|
||||
type readCloser struct {
|
||||
|
@ -108,3 +163,9 @@ func CheckHttpResponseStatusCode(resp *http.Response) error {
|
|||
}
|
||||
return errors.New("Error: unexpected response status code")
|
||||
}
|
||||
|
||||
func LogDebug(s string) {
|
||||
if len(os.Getenv("LOG_DEBUG")) != 0 {
|
||||
log.Printf(s)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue